Closed8
イベント伝播
毎回忘れるやつ
こういうやつ
<div class="e1">
e1
<div class="e2">
e2
<div class="e3">e3</div>
</div>
</div>
デフォルトでは、子から親にバブリングフェーズでイベントが伝わっていく
e1クリック → e1
e2クリック → e2 → e1
e3クリック → e3 → e2→ e1
const e1 = document.querySelector(".e1");
const e2 = document.querySelector(".e2");
const e3 = document.querySelector(".e3");
const options = {
e1: {
passive: false,
capture: false,
},
e2: {
passive: false,
capture: false,
},
e3: {
passive: false,
capture: false,
},
};
const call = (e) => {
// e.stopPropagation();
alert(e.currentTarget.className);
};
e1.addEventListener(
"click",
(e) => {
call(e);
},
{ ...options.e1 }
);
e2.addEventListener(
"click",
(e) => {
call(e);
},
{ ...options.e2 }
);
e3.addEventListener(
"click",
(e) => {
call(e);
},
{ ...options.e3 }
);
stopPropagation
で伝播が止まる。
バブリングされないようになる。
e.stopPropagation();
alert(e.currentTarget.className);
};
e1クリック → e1
e2クリック → e2
e3クリック → e3
const options = {
e1: {
passive: false,
capture: true,
},
e2: {
passive: false,
capture: true,
},
e3: {
passive: false,
capture: true,
},
};
const call = (e) => {
// e.stopPropagation();
alert(e.currentTarget.className);
};
e1.addEventListener(
"click",
(e) => {
call(e);
},
{ ...options.e1 }
);
e2.addEventListener(
"click",
(e) => {
call(e);
},
{ ...options.e2 }
);
e3.addEventListener(
"click",
(e) => {
call(e);
},
{ ...options.e3 }
);
capture: true
にしたらキャプチャリングフェーズでイベントが実行される
e1クリック → e1
e2クリック → e1 → e2
e3クリック → e1 → e2 → e3
で、さらにstopPropagation
を適用
const call = (e) => {
e.stopPropagation();
alert(e.currentTarget.className);
};
伝播が止まる
e1クリック → e1
e2クリック → e1
e3クリック → e1
preventDefault
はイベントに備わった動作をキャンセルするもの。
イベントの伝播は止まらない。
const call = (e) => {
e.preventDefault(); // 伝播は止まらない!
alert(e.currentTarget.className);
};
こういうことをすると、以下のエラーが出る。
Unable to preventDefault inside passive event listener invocation.
{passive:true}
の状態ではイベントリスナーの中で
「preventDefaultは使ってません!」という状態なので、矛盾が生じる。
上記によって、パフォーマンスをあげているわけなので。
const options = {
e1: {
passive: true,
capture: false,
},
e2: {
passive: true,
capture: false,
},
e3: {
passive: true,
capture: false,
},
};
const call = (e) => {
// e.stopPropagation();
e.preventDefault();
alert(e.currentTarget.className);
};
そのため、React では wheel イベントや touch イベントなど即時反映が求められるイベントに対して、Passive モードを有効にしています。
Reactでは、デフォで、passive:true
になっているイベントがあるので、
preventDefault
でエラーが出る場合があるので。注意が必要。
このスクラップは2025/01/01にクローズされました