質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

2回答

333閲覧

jqueryでバブリングの仕様について

vowd1

総合スコア53

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2018/05/12 17:44

javascript

1 $("ul").on("click","li",function(){ 2 $(this).addClass('select'); 3 });

上記のようなjqueryが実行されると、li要素にしかclassが付与されませんが、イベントバブリングでul要素にもclass名が付与されないのはなぜですか。また、ul要素にもclass名を付与するにはどのような書き方をすべきですか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
think49

総合スコア18164

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

vowd1

2018/05/13 07:12

回答ありがとうございます。 なるほどネストしているときはこんな方法で取得しないとできない場合もあるんですね。おそらく発火が3回の場合はメモリ消費も無駄にかかってしまうので避けるべきなのでしょうね。大変勉強になりました。
guest

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

m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

vowd1

2018/05/13 07:01

最初の指定されるオブジェクトはあくまで調査範囲であり、実際に$(this)に該当するのはonメソッドの第二引数ということですね。 もう少しメソッドの仕様について調べる必要がありそうです。ありがとうございました。BAとさせていただきます。
m.ts10806

2018/05/13 08:25

理解が進んだようで何よりです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問