1

次の要素があるとします。

+------------------+
|                  |
|    +----------------+
|    |                |
|    |                |
|    +----------------+
|                  |
+------------------+

内側の要素には、親の外側に視覚的に配置できる位置付けがあり、次のように親にイベント リスナーを配置します。

parent.addEventListener('mouseover', function(e) {
  // log mouse is over me
}, false);

下から親に直接マウスを合わせると、直接イベントが発生しますが、横からマウスを合わせると (最初に子を押すと) イベント ルーティングが発生するため、子がバブルアップするときにも子からイベントを受け取ります。 .

子要素から出て親スペースに入るまで左に移動し続けると、直接イベントが発生し、もう一度右に移動すると、子要素から別のバブル イベントが発生します。

これは設計によるものであり、設計はまったく問題ありませんが、マウスが私の上にあるときに単一のアクションを実行したい場合 (子アイテムを含む)、興味のないイベントをブロックするために追加の作業を行う必要があります。 . たとえば、これはうまくいきます:

var isOver = false;

parent.addEventListener('mouseover', function(e) {
  if (isOver) return;
  isOver = true;
  // log mouse is over me
}, false);

parent.addEventListener('mouseout', function(e) {
  if (e.relatedTarget == this || e.relatedTarget.isDescendantOf(this)) return;
  isOver = false;
  // log mouse is leaving me
}, false);

基本的に、コードには、マウスが (子を介してかどうかに関係なく) 親を「オーバード」したかどうかを判断する状態変数があり、「オーバード」している間にイベントが再び発生した場合、それらのイベントは無視されます。マウス アウト イベントもキャプチャします。聞いてみてください.. relatedTarget (あなたが入力しようとしているターゲット) は私ですか? (親)、またはMEの最終的な子供?そうであれば、何もしないでください。それ以外の場合は、「overed」状態を false に設定します。

そのコードは実際には機能しますが、次のターゲットを決定するために relatedTarget プロパティを使用できないと想像してください。この動作を行うにはどうすればよいでしょうか?

私はそれが理にかなっていることを願っています。関連するターゲットなしでそれを行うには、イベントに十分なコンテキストがないと感じていますが、eventPhase プロパティの動作を変更することに関して角度があるかもしれないと感じました (イベントが直接かバブルかを判断するため)。

また、「これは IE では機能しません、ヤッダヤッダ」という回答を探しているわけではありません。


編集、明確にするために、次のように見える単一の要素があるかのようにイベントが発生するようにします(要素が実際に上記の例の場合):

+------------------+
|                  |
|                  +--+
|                     |
|                     |
|                  +--+
|                  |
+------------------+
4

2 に答える 2

2

あなたが求めているのは、IE の"mouseenter"イベント (ユーザーがマウス ポインターをオブジェクトの境界内に移動したときに発生する) と"mouseleave"イベント (ユーザーがマウス ポインターをオブジェクトの境界外に移動したときに発生する) だと思います。

イベントとは異なり、onmouseoverイベント onmouseenterはバブルしません。つまり、onmouseenterユーザーがオブジェクトに含まれる要素の上にマウス ポインターを移動してもイベントは発生しませんが、発生しonmouseover ます。

についても同様ですonmouseleave

以下に例を示します: http://jsbin.com/uputi/edit ( URL に追加してソース コードを編集します):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
<head> 
<title>Sandbox</title> 
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen"> 
#outer { width:200px; height:200px; border:1px solid #333; }
#inner { float:right; width:125px; height:80px; margin-right:-80px; border:1px solid #333; }
</style> 

<script> 
window.onload = function() {
  function mouseenter() {
    document.getElementById('dbg').innerHTML = 'mouse entered #outer boundary';
  }

  function mouseleave() {
    document.getElementById('dbg').innerHTML = 'mouse left #outer boundary';
  }

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

  if ('onmouseenter' in document.body) {
    // browser supports mouseenter/mouseleave natively (i.e., IE)
    outer.onmouseenter = mouseenter;
    outer.onmouseleave = mouseleave;
  }
  else {
    // simulate mouseenter/mouseleave in other browsers
    function wrap(fn) {
      return function(event) {
        var parent = event.relatedTarget;

        // Check if we're still within the same parent (traverse up parentNodes)
        while (parent && parent != this) {
          parent = parent.parentNode
        }

        if(parent != this) {
          // call the *real* mouseover/mouseout handler
          fn.call(this, event)
        }
      }
    }

    outer.onmouseover = wrap(mouseenter);
    outer.onmouseout = wrap(mouseleave);
  }
}
</script> 
</head> 
<body> 
  <div id="outer"> 
    <div><code>#outer</code></div> 
    <div>&nbsp;</div> 
    <div>&nbsp;</div> 
    <div id="inner"><code>#inner</code></div> 
  </div> 
  <div id="dbg"></div> 
</body> 
</html>

それはあなたがするように使用relatedTargetします(これは標準ブラウザFYIでうまく動作します)が、状態フラグはありません。ここに示されているエミュレーションの詳細については、この記事を参照してください。要素と要素mouseenterに入ると、1 つのイベントだけが発生することがわかります。これは、あなたが求めている「境界」効果です(私は思います)。#outer#inner

アプリケーションに jQuery を含めるオプションがある場合、j Query はこれらの素晴らしいイベントを他のブラウザーにもたらします。(jQuery は、彼女が内部で概説した手法を使用し、いくつかのマイナーな変更を加えていることに注意してください)。

プロトタイプ 1.6.1では、これらのイベントもシミュレートされています。

于 2009-11-04T16:34:46.750 に答える
0

私はあなたが単にPropagationを停止する必要があると思います

于 2009-11-04T15:40:03.600 に答える