【jQuery】『mouseover』が複数回発生してしまう時の対処方法

Pocket
LINEで送る

jQueryで『mouseover』や『mouseout』を使って動的な動きを付けようとしたときに「あれ、何度も発火してしまう・・」と謎の挙動を繰り返す事態にでくわしました。
なので、その状態の説明と改善方法についてまとめます。

問題点:イベントが複数回発生する

解決方法の前に、そもそも何故『mouseover』を利用するとイベントが複数回発生してしまうのでしょうか。

原因

『mouseover』を使ってイベントを発火させると、セレクターの子要素でも発火されてしまい、セレクター内で複数回イベントが起こってしまうからです。
それでは一度、実際のサンプルをもとに説明していきます。

デモ

<p id="target">#target<span>span</span></p>
<p><span id="num">0</span>回マウスオンされました。</p>
var num = 0;
jQuery(function(){
   jQuery('#target').mouseover(function(){
      num++;
      jQuery('#num').html(num); // カウントを表示させています。
   });
})

#targetspan

0回マウスオンされました。

jQueryでセレクターとして指定している『#target』だけではなく、子要素の『span』にカーソルがのったときにもイベントが発火しているのがわかるかと思います。

これは、上でも書いたように『mouseover』を使ってイベントを発火させると、セレクターの子要素でも発火されてしまうからなのです。

そのため『mouseover』を利用して要素に動きを付ける指定をしたときに、予期せぬ挙動を起こしてしまうことになっていたのです。

『mouseout』でも同様の挙動が発生します。

ちなみに、『on』を用いて試した結果が下記になります。

『on』を代用してみる

<p id="target">#target<span>span</span></p>
<p><span id="num">0</span>回マウスオンされました。</p>
var p1 = 0;
jQuery(function(){
   jQuery('#target').on('mouseover',function(){
      p1++;
      jQuery('#num').html(p1); // カウントを表示させています。
   });
})

#targetspan

0回マウスオンされました。

結果:変わらず複数回イベントが発生します。

解決策:『mouseenter』『mouseleave』を利用する

イベントが複数回発生してしまうことを防ぐためには『mouseenter』『mouseleave』を利用しましょう。【jQuery入門講座】の情報がわかりやすかったので紹介しておきます。

mouseoverとmouseenterの違い
コンテンツ作成においてマウスオーバーの処理はよく利用されます。jQueryではマウスオーバーに関連するイベントは2つ(mouseoverイベントとmouseenterイベント)あり初心者にとって分かりにくいので、ここで説明します。2つの違いはセレクタで指定した要素内に別の要素がある(入れ子構造の)時に生じます。
【出典:jQuery入門講座 使い方-イベントフロー(3)・http://www.jquerystudy.info/tutorial/applied/flow3.html・2015/11/22】

デモ

<p id="target">#target<span>span</span></p>
<p><span id="num">0</span>回マウスオンされました。</p>
var num = 0;
jQuery(function(){
   jQuery('#target').mouseenter(function(){
      num++;
      jQuery('#num').html(num); // カウントを表示させています。
   });
})

#targetspan

0回マウスオンされました。

ちゃんと、外のtargetに乗った時だけに発火するようになり、複数回の発生はなくなりましたね。

『mouseover』や『mouseout』などを利用するときは、その影響範囲が子要素まで及ぶことを理解しておきましょう。

おわりに

これ昔にめちゃくちゃハマりました。。体系的に理解ができていないと、本当コーディング時に困るなぁとみにつまされました。

SNSでもご購読できます。