javascript
1 $("ul").on("click","li",function(){ 2 $(this).addClass('select'); 3 });
上記のようなjqueryが実行されると、li要素にしかclassが付与されませんが、イベントバブリングでul要素にもclass名が付与されないのはなぜですか。また、ul要素にもclass名を付与するにはどのような書き方をすべきですか。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
addEventListener
イベントバブリングという言葉から、質問者さんは DOM Events としてそのコードを見ているのだと思います。
JavaScript
1document.querySelector('ul').addEventListener('click', function handleClick (event) { 2 console.log(event.currentTarget, this); // <ul>, <ul> 3}, false);
DOM Events 的には、「this
値はul要素ノードを参照する」が正しいのですが、mts10806 さんが回答して下さっているように jQuery API はその機能を拡張しています。
.on( events, selector, handler )
.on()
の第二引数にセレクタ文字列が指定された場合、event.currentTarget
(及び this
値) の参照値は第二引数で指定される対象ノードに束縛されます。
参照値だけなら、次のコードは全て等価です。
JavaScript
1/** 2 * (A) 3 */ 4jQuery('ul').on('click', 'li', function (event) { 5 console.log(event.currentTarget, this); // <li>, <li> 6}); 7 8/** 9 * (B) 10 */ 11jQuery('li').on('click', function (event) { 12 console.log(event.currentTarget, this); // <li>, <li> 13}); 14 15/** 16 * (C) 17 */ 18for (let li of document.querySelectorAll('ul')) { 19 li.addEventListener('click', function handleClick (event) { 20 console.log(event.currentTarget, this); // <li>, <li> 21 }, false); 22}
勿論、(A) がイベントバブリングで参照するのはul要素ノードであり、動的に追加されたli要素ノードにも対応できることから、内部的な動作は異なります。
ul要素とli要素は親子関係にある為、li要素ノードの親ノードを辿れば目的が達成できる、とほぼいえます。
「ほぼ」というのは、ul要素がネストしている場合にこの前提が崩れるからです。
HTML
1<ul> 2 <li>target1</li> 3 <li> 4 <ul> 5 <li>target2</li> 6 </ul> 7 </li> 8</ul> 9<script> 10'use strict'; 11jQuery('ul').on('click', 'li', function (event) { 12 console.log(event.currentTarget, this); // <li>, <li> 13}); 14</script>
この場合は「3回、clickイベントハンドラが発火してしまう」という問題もあります。
ul要素とli要素が孫関係となる場合、li要素ノードから元々の event.currentTarget
(ul要素ノード) を得る方法はありません。その為、第二引数で event.currentTarget
を束縛しないコードに変更する必要があります。
JavaScript
1<ul id="target"> 2 <li>target1</li> 3 <li> 4 <ul> 5 <li>target2</li> 6 </ul> 7 </li> 8</ul> 9<script> 10'use strict'; 11jQuery('#target').on('click', function (event) { 12 console.log(event.currentTarget, this); // <ul>, <ul> 13 14 var ul = event.currentTarget, 15 li = event.target; 16 17 while (ul !== li.parentNode) { 18 li = li.parentNode; 19 } 20 21 console.log(li); // event.currentTarget を親に持つ <li> 22}); 23</script>
今回はul要素がネストした場合でコードを考えましたが、実際にはネストでなくとも、孫関係にある要素ノードに束縛したいケースがそれなりにあります。
そういう場合に jQuery#on
の第二引数(セレクタ)は使いづらいので、あえて使わない方法を採用する事があります。
Re: vowd1 さん
投稿2018/05/13 01:57
編集2018/05/13 02:03総合スコア18164
0
ベストアンサー
確認をしてみれば分かります。
js
1$(function(){ 2 $("ul").on("click","li",function(){ 3 console.log($(this)); 4 }); 5})
とした場合、
w.fn.init [li]
とコンソールに出力されます。
最初のエレメント指定、今回は$("ul")はあくまで「調査範囲」として認識されます。
その中で指定した「セレクタ」を探すことになり、該当したものがあればそちらがthisとして扱われるようになります。
調査範囲について
onメソッドの構文では、要素を第2引数の「セレクタ」で設定します。そして最初のjQueryオブジェクトには調査範囲を指定します。動的な要素にイベント発生時の処理を設定できるのは非常に便利ですが、これを実現するためにはイベントが発生するたびにDOMの状態を確認しなければならず、そのため負荷が高いのです。
そこで負荷を減らすためにDOM全体を調べるのではなく「調査範囲を設定して」その範囲でしかイベントの発生を確認しないことで負荷を下げているのです。
質問内容のケースで親であるulにもクラスを付与するのであれば、そのthisの親、という形で指定すれば良いです。
js
1$(function(){ 2 $("ul").on("click","li",function(){ 3 $(this).addClass('select'); 4 $(this).parent().addClass('付与したいクラス名'); 5 }); 6})
投稿2018/05/12 21:10
総合スコア80850
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/05/13 07:12