2011-11-18 21 views
7

ご存じのように、イベントは通常javascriptでバブルアップするので、イベントを発生させる要素のイベントハンドラが最初に実行され、次に親要素のイベントハンドラが呼び出されます。この動作は、私が現在取り組んでいるプロジェクトでいくつかの問題を引き起こし、むしろ実行順序を逆にすることになります。javascriptのイベントのバブリングを逆にする

私はタイムアウトを使用しているソリューションをfiguered:

$(element).mouseover(function(){ 
    var that = this; 
    setTimeout(function() { 
     //actual event handler, but references to "this" are replaced with "that" 
    },$(this).parents().length) 
}); 

だから、基本的には、イベントハンドラが短いタイムアウトの後に実行され、待機時間がDOMツリー内の要素の深さに依存: html要素のイベントハンドラはすぐに実行され、body要素のイベントハンドラは1ms待ってから実行されます。したがって、イベントの実行順序は逆になります。

私の最初のテストの結果は肯定的ですが、この解決策に問題や欠点があるかどうかはまだ分かりません。この解決策についてどう思いますか?この問題を解決するための他のアイデアも高く評価されています。

+1

私は親の*量*をタイムアウトのミリ秒単位で*設定する理由を理解していません。 – pimvdb

+2

これは、リーフ要素のイベントハンドラを実行するのが遅れて、最後にチェーン内で実行されるようにするためです。 – WTK

答えて

14

リバースイベントバブリングをキャプチャフェーズと呼びます。

は、それが、キャプチャ段階、それは従来のプラットフォームでは動作しませんもちろん

el.addEventListener("click", function() { 
    console.log("i run in capture"); 
}, true); 

でトリガ持ってEvent.addEventListenerの第三引数としてDOM event architecture

パスtrueを参照してください。イベントシステムをエミュレートするには、DOM3イベントシムが必要です。貢献すること自由にDOM-shim

+0

ええ、確かに、それはすべてのブラウザで実装されていません。こちらをご覧くださいhttp://www.quirksmode.org/js/events_order。html – WTK

+1

@WTK誰が従来のプラットフォームを気にしていますか? – Raynos

+3

@Raynosクライアント^^ –

0

あなたの解決策の大きな欠点は、処理されたイベントごとにDOMを上向きにトラバースして、親の数を確定することです。これはthisから始まります。

すべてのイベントハンドラでこのような方法でトラバースする=パフォーマンスが低い。

+0

イベントが発生するたびに、ドキュメントルートからイベントをトリガした要素まで、次にルートまで戻ってきます。ハンドラコードのドキュメントルートまで余分な時間を費やすことは、余計な時間を費やすことにはなりません。 –

0

あなたはそれをエミュレートしようとすることができますが、おそらくそれは多くの問題を引き起こす可能性があります。

非常に簡単な例です(jsfiddle)。 考え方は、各イベントのコールバックを集約し、documentイベントハンドラで逆順に呼び出します(次のクリック時に新しいキューを確保するためにリストもクリアします)。

<div id="a"> 
    <div id="b"> 
     <a href="/test">Click Me!</a> 
    </div> 
</div> 
var cb = []; 

$(document).click(function(evt){ 

    cb.unshift(function(){ 
     console.log('document'); 
    }); 
    var i; 
    for(i=0; i<cb.length; ++i){ 
     cb[i].call(null, evt); 
    } 
    cb = []; 
}); 

$("#a").click(function(){ 
    cb.unshift(function(){ 
     console.log('div#a'); 
    }); 
}); 

$("#b").click(function(){ 
    cb.unshift(function(){ 
     console.log('div#b'); 
    }); 
}); 

$('a').click(function(evt){ 
    cb.unshift(function(evt){ 
     evt.preventDefault(); 
     console.log('a'); 
    }); 
}); 

たぶん、あなたは、あなたのデザインを変更する必要がありますか?より多くの情報を投稿できますか、なぜイベントキャプチャが必要ですか?

+0

あなたの答えをありがとう。このリバースイベントハンドラの実行が必要な理由は非常に複雑で、簡単に説明することができません。基本的には、任意のhtmlドキュメントのさまざまな要素にマウスオーバーハンドラーがあります。通常、内側の要素に到達する前に外側の要素にマウスポインタを移動するため、外側の要素のイベントハンドラが最初に実行されますが、内側の要素を含む要素にはパディングはありません。内側の要素に移動するために外側の要素を移動します。私は一貫した振る舞いのために順序を逆にしたいと思います。 – Simon

+0

うーん...あなたはいつも、ある種の「継承」をここで使うことができます:http://jsfiddle.net/GEFAq/ 2 /そしてそれはうまくいくはずです(私が見る限り、トリガーは同期しています)。これは基本的なコンセプトです。要素ハンドラの伝播を停止し、他のアクションを実行する前に親要素で同じイベントをトリガします。 –

+0

しかし、もしあなたが本当に古いブラウザを気にかけていないのであれば、気にしないで@Raynosの解決策にしてください:) –

関連する問題