2017-09-11 2 views
0

HyperHTMLElementを使用する場合は、要素であるため、this.childrenまたはthis.querySelector()を使用するだけでコンポーネントの内容にアクセスできます。hyper.Componentを使用する場合のDOMへのアクセス

しかし、hyper.Componentを使用すると、同様の動作をどのように達成できますか?

私が心に留めている事実はReact docsです:https://facebook.github.io/react/docs/refs-and-the-dom.html - DOMの中に特定のノードを集中させたいと思います。

私はこの問題を解決しようとしているcodepenサンドボックスがあります。アイデアはrender()が同じNodeを毎回返すので、私は返す前にそれを保存してthis.nodeとして、後でそれにアクセスできることであるhttps://codepen.io/asapach/pen/oGvdBd?editors=0010

を:

render() { 
    this.node = this.html` 
    <div> 
     <input type="text" /> 
     <input type="button" value="Focus the text input" onclick=${this} /> 
    </div> 
    `; 
    return this.node; 
} 

しかし、それは私には見えません。これを行うより良い方法はありますか?

答えて

2

handleEventパターンがあります。そのパターンの背後にあるアイデアは、動作がイベントドリブンである場合にDOM参照を保持する必要がないということです。なぜなら、常にリスナーが接続されている要素を指しているevent.currentTarget、またはクリックに適したevent.targetあなたのデモケースではdivのラップ要素に添付されたジェネリッククリックハンドラ内の他の場所にもあります。

これらの情報を使用する場合は、ルート要素のdata-is="custom-text-input"のような属性を使用してコンポーネントを拡張し、必要な他のことを行うことができます。 https://codepen.io/WebReflection/pen/LzEmgO?editors=0010

:この他のフォークのように、あなたのコンポーネントをレンダリングし、一度そのコンテンツを扱うことができ、代替案として https://codepen.io/WebReflection/pen/RLNyjy?editors=0010

onclick(e) { 
    var node = e.target.closest('[data-is=custom-text-input]'); 
    node.querySelector('[type=text]').focus(); 
} 

あなたはあなたのコードペンのフォークに作業例を見ることができます

constructor() { 
    super().node = this.render(); 
    } 

あなたはカスタム要素を使用せず、基本的なgood'ol DOMノードを使用すれば、必要なときにいつでも初期化/レンダリングできますアップグレードメカニズムを待つ。

DOMエレメントに関連するインスタンスをアドレス指定/変更/突然変異させる方法はありません。

これらの可能性があなたの質問に答えてくれることを願っています。

+0

私はオプションとして 'event.target'を使うことを考えていました。 – DreamSonic

+0

コンストラクタで 'render()'を呼び出すのは本当に良い考えですか? – DreamSonic

+2

ルートノードを参照する必要がある場合は、レンダリングを遅かれ早かれ呼び出すことで違いはありません。同じコンテンツでhyperHTMLコンテンツを2回更新するコストはゼロに近いため、後でコンポーネントを再レンダリングしてもパフォーマンスの問題は発生しません。しかし、実際にルートノードに直接アクセスする必要のある重要ではないコンポーネントの場合は、イベント駆動型の方法でDOMを操作することをお勧めします。それは確かにきれいです。 –

0

これは、実装は実際には非常に簡単ですhttps://github.com/joshgillies/hypercomponent

を経由して、私が過去に働いてきたものです。

class ElementalComponent extends hyper.Component { 
    constructor() { 
    super() 
    const _html = super.html 
    this.html = (...args) => { 
     this.node = _html.apply(this, args) 
     return this.node 
    } 
    } 
} 

class HelloWorld extends ElementalComponent { 
    render() { 
    return this.html`<div>Hello World!</div>` 
    } 
} 

これは本当にうまく動作し、あなたの質問とインラインです。しかし、hyperHTMLは単一のノードだけでなく複数のノードをレンダリングすることができます。例として:

hyper`<div>Hello World!</div>` // returns a single DOM Node 
hyper`<div>Hello</div> <div>World!</div>` // returns multiple DOM Nodes as an Array. 

したがって、上記のElementalComponentthis.nodeはレンダラーがやっていることに基づいてDOMノード、またはArrayのいずれかになります。

関連する問題