javascriptにおけるmouseoverとmouseoutイベントの最適化
3949 ワード
前に開発をした時にこの問題に出会いました.
あるコンテナにオンモスoverまたはonmouseoutイベントをバインドした場合、このコンテナに他の要素ノードがあると、マウスが内部を移動する時に、onmouseoverとonmouseoutイベントを頻繁にトリガします.これは実例があります.他の人のは参考にしてください.
私が欲しい効果は、イベントがマウスの中に入る時と離れる時だけです.マウスが元素範囲の中を移動する時はトリガしません.
なぜこの原因が現れますか?実は事件の泡が発生したためです.マウスを上に移動したり、コンテナの中のサブノードを移動したりすると、それぞれmouseoverとmouseoutイベントがトリガされ、domツリーに沿って上に泡が発生して、イベントハンドラ(モニター)によって捕獲されたり、ルートノード(documentまたはwindow)に泡ができたりするまで、つまりイベントは親レベルのオブジェクトに送られます.
問題の原因が分かりました.解決するのも簡単ですか?最初に考えたのは、イベントの泡をキャンセルし、event.ccerBbble=true(IE)とe.stopPropagation(他のブラウザ)を使っていましたが、簡単なテストの後、効果がないようです.(補足:私はテストで容器の中のaリンクノードを発泡解除しましたが、マウスが上に移動するとイベントが発生することが分かりました.Aノードの下にはspanノードがあります.容器の中のすべてのノードを泡にしないといけませんか?心ある人はテストできます.もし本当にこのようにすれば、それはとても気持ちが悪いです.N個のノードなら、泡を止めるべきですか?)
実はIEの下でマウスのイベントはmouse Enterとmouse Leaveがあります.これは移動と移動の際にトリガします.内部移動はトリガしません.残念なのはIEのみです.私たちが今やるべきことは、「非IEブラウザにモバイルEnterとmouse Leaveサポートを追加する」ということです.
jQueryはそうではありません.IEと他のすべてのブラウザでmouseoverとmouseoutイベントを直接修正しました.jQueryを参考にして、今のコードを全部もらいました.
まず、ノードオブジェクトが含まれているかどうかを判断する関数containsを紹介します.
もちろん、上のコードを単独でmouse Enterとmouse Leaveにパッケージ化してもいいです.これによって、mouseoverとmouseoutをもっと区別して呼び出すことができます.
具体的なデモについては、私が新しいテーマでオンラインする時に皆さんに見せてください.またはここのコメントの応答、参照ボタンの明示的な隠蔽を見て、上述のように用いられた.
あるコンテナにオンモスoverまたはonmouseoutイベントをバインドした場合、このコンテナに他の要素ノードがあると、マウスが内部を移動する時に、onmouseoverとonmouseoutイベントを頻繁にトリガします.これは実例があります.他の人のは参考にしてください.
私が欲しい効果は、イベントがマウスの中に入る時と離れる時だけです.マウスが元素範囲の中を移動する時はトリガしません.
なぜこの原因が現れますか?実は事件の泡が発生したためです.マウスを上に移動したり、コンテナの中のサブノードを移動したりすると、それぞれmouseoverとmouseoutイベントがトリガされ、domツリーに沿って上に泡が発生して、イベントハンドラ(モニター)によって捕獲されたり、ルートノード(documentまたはwindow)に泡ができたりするまで、つまりイベントは親レベルのオブジェクトに送られます.
問題の原因が分かりました.解決するのも簡単ですか?最初に考えたのは、イベントの泡をキャンセルし、event.ccerBbble=true(IE)とe.stopPropagation(他のブラウザ)を使っていましたが、簡単なテストの後、効果がないようです.(補足:私はテストで容器の中のaリンクノードを発泡解除しましたが、マウスが上に移動するとイベントが発生することが分かりました.Aノードの下にはspanノードがあります.容器の中のすべてのノードを泡にしないといけませんか?心ある人はテストできます.もし本当にこのようにすれば、それはとても気持ちが悪いです.N個のノードなら、泡を止めるべきですか?)
実はIEの下でマウスのイベントはmouse Enterとmouse Leaveがあります.これは移動と移動の際にトリガします.内部移動はトリガしません.残念なのはIEのみです.私たちが今やるべきことは、「非IEブラウザにモバイルEnterとmouse Leaveサポートを追加する」ということです.
jQueryはそうではありません.IEと他のすべてのブラウザでmouseoverとmouseoutイベントを直接修正しました.jQueryを参考にして、今のコードを全部もらいました.
まず、ノードオブジェクトが含まれているかどうかを判断する関数containsを紹介します.
/* p=parentNode, c=childNode */
function contains(p,c){
return p.contains ?
p != c && p.contains(c) :
!!(p.compareDocumentPosition(c) & 16);
}
ここで私たちはIEの下でfrom ElementとtoElementを使いました.この二つはIEの下でマウスを上に移動した時と移動した時のノードオブジェクトです./* e ,target */
function fixedMouse(e,target){
var related,
type=e.type.toLowerCase();//
if(type=='mouseover'){
related=e.relatedTarget||e.fromElement
}else if(type='mouseout'){
related=e.relatedTarget||e.toElement
}else return true;
return related && related.prefix!='xul' && !contains(target,related) && related!==target;
}
それから私たちはどう使いますか?イベントをバインドする時、//addListener
addListener(target,'mouseover',function(e){
e=e||window.event;
if(fixedMouse(e, target)){
//do something
}
},false);
これは、ターゲットノードを移動する際にのみ、mouseoverとmouseoutをトリガすることになる.もちろん、上のコードを単独でmouse Enterとmouse Leaveにパッケージ化してもいいです.これによって、mouseoverとmouseoutをもっと区別して呼び出すことができます.
具体的なデモについては、私が新しいテーマでオンラインする時に皆さんに見せてください.またはここのコメントの応答、参照ボタンの明示的な隠蔽を見て、上述のように用いられた.