2012-02-02 4 views
20

動的に作成された要素にイベントをバインドする方法を理解しようとしています。それが破壊され再生された後でも、その要素を維持するためのイベントが必要です。jQueryの「ライブ」バインダーをネイティブJavaScriptで実装する

明らかにjQueryのライブ機能は簡単ですが、ネイティブのJavascriptで実装されたように見えますか?ここで

+1

いつでもjQueryソースを読むことができます:p。しかし、それがネイティブJSからどのくらい離れているかはわかりませんが、セレクタやその他のものを使用するという点では、それがかなり重くなると確信しています。 – Corbin

+0

ちょうど1つの注意: '.live()'は長い間長い間使われなくなりました。 '.delegate()'に置き換えられ、 '.on()'に置き換えられました。最後のものを使用してください。さらに、最後のものはバインディングと委任の違いを示していますので、見てみたいかもしれません。最も重要なのは、イベントターゲットをチェックすることです。 – Tadeck

+0

私のこの答えは助けるかもしれませんhttp://stackoverflow.com/a/27373951/1385441 –

答えて

21

は簡単な例です:

function live(eventType, elementId, cb) { 
    document.addEventListener(eventType, function (event) { 
     if (event.target.id === elementId) { 
      cb.call(event.target, event); 
     } 
    }); 
} 

live("click", "test", function (event) { 
    alert(this.id); 
}); 

基本的な考え方は、ドキュメントにイベントハンドラをアタッチし、DOMアップイベントバブルを聞かせたいということです。次に、event.targetプロパティをチェックして、目的の条件(この場合は要素のid)と一致するかどうかを確認します。

は編集:

@shabuncが正しく検出されない子要素の私のsolution--イベントで非常に大きな問題を発見しました。この問題を解決する一つの方法は、任意の指定されたidを持っているかどうかを確認するために祖先要素を見ることである。

function live (eventType, elementId, cb) { 
    document.addEventListener(eventType, function (event) { 
     var el = event.target 
      , found; 

     while (el && !(found = el.id === elementId)) { 
      el = el.parentElement; 
     } 

     if (found) { 
      cb.call(el, event); 
     } 
    }); 
} 
+0

あなたの興味のある要素を期待していない外のコンテナに、文書に - またはより効率的に - 。 – Tadeck

+0

これはちょうど任意のクリックイベントをリッスンし、クリックイベントが発生すると、ターゲットのIDが指定されたIDと一致するかどうかをチェックし、コールバック関数を実行します。かなり面白い:) – InspiredJW

+0

右。また、@Tadeckが指摘しているように、より効率的なリスナーのために、バブリングを別の要素に制限することができます。 –

14

アンドリューズポストとBinyaminさんのコメントに加えて、多分これはオプションです。これにより

することができますセレクタとして 'nav。aem'を使用してください。 Andrewのコードに基づいています。

function live (eventType, elementQuerySelector, cb) { 
    document.addEventListener(eventType, function (event) { 

     var qs = document.querySelectorAll(elementQuerySelector); 

     if (qs) { 
      var el = event.target, index = -1; 
      while (el && ((index = Array.prototype.indexOf.call(qs, el)) === -1)) { 
       el = el.parentElement; 
      } 

      if (index > -1) { 
       cb.call(el, event); 
      } 
     } 
    }); 
} 



live('click', 'nav .aap a', function(event) { console.log(event); alert('clicked'); }); 
+0

ありがとうございました。私が提案したいことの1つは、 'addEventListener'の中で' e.preventDefault() 'をサポートすることです。もし使用されている場合は、それを 'document.querySelector(elementQuerySelector).addEventListener(eventType、function(event){' elseに変更する必要があります。 – Lodder

0

イベントを特定の要素に動的にバインドする代わりに、グローバルイベントリスナーを使用できます。したがって、その要素の別の新しい要素イベントでDOMを更新するたびに、「キャッチ」も発生します。例:この例では

var mybuttonlist = document.getElementById('mybuttonlist'); 
 

 
mybuttonlist.addEventListener('click', e=>{ 
 
    if(e.target.nodeName == 'BUTTON'){ 
 
    switch(e.target.name){ 
 
     case 'createnewbutton': 
 
     mybuttonlist.innerHTML += '<li><button name="createnewbutton">Create new button</button></li>'; 
 
     break; 
 
    } 
 
    } 
 
}, false);
ul { 
 
    list-style: none; 
 
    padding: 0; 
 
    margin: 0; 
 
}
<ul id="mybuttonlist"> 
 
    <li><button name="createnewbutton">Create new button</button></li> 
 
</ul>

私はクリックイベントのため<ul>にイベントリスナーを持っています。したがって、イベントはすべての子要素に対して発生します。私が作成したシンプルなイベントハンドラから、より多くのロジック、ボタン(異なる名前または繰り返しの名前)、アンカーなどを追加するのが簡単であることがわかります。

すべてに入ると、リスト要素は、ページ上のすべてのクリックイベントを捕捉してから、イベントハンドラ内のクリックイベントを処理します。

関連する問題