##やりたいこと
モーダルを開いたときに、「パソコンのスクロールを一時的止めたいな」
と思うことがありました。
とりあえずかいてみました。
window.addEventListener('mousewheel',(e)=>{
e.preventDefault();
});
preventDefaul
でスクロールの動きを封じるやつです。
でもエラーが出て全然動きません。
##スクロールジャンク防止が原因だった
↓こちらのサイトでスクロールジャンクを知りました。
https://blog.webico.work/passive-event-listeber01
どうやら、スクロール系のイベント(mousewheel
,touchmove
,wheel
など)は、
スクロールするたびに登録された全てのイベントにpreventDefault()
がないか確認が終わるまで処理が行えないそうです。これが所謂スクロールジャンク。
それを防ぐためにaddEventListener
にはpassive:trueという値が初期値で設定されています。
これは実行前に、「preventDefault()
実行しませんよ〜」と明示するものらしいです。
でも!
今回はprevcentDefault()
を実行するので、ここの値をいじります。
##解決方法は?
passiveにfalseを渡してあげましょう。
window.addEventListener('mousewheel',(e)=>{
e.preventDefault();},{passive:false});
ちょっと待って!
昨日調べたことによると、イベントリスナの第三引数はuseCapture
というイベント伝播に関する引数だったはず...
##addEventListenerの第三引数の謎
https://qiita.com/kozy4324/items/85831e2c990d92b8397b
こちらの記事に答えがありました。
元々はuseCapture
のみだったみたいですが、拡張されたようです。現在では
element.addEventListener('click',Handler(),{
once: true,
passive: true,
capture: true
});
と書けるとのこと。
(以前の書き方と互換性があり、第三引数にboolean型のみ渡した場合はcaptureの値として判断されるそうです。)
###onceってなに?
once
にすると、イベントハンドラが一度だけ処理されます。
一度しか読み込まないイベントを明示することで、メモリの節約になる!ってことですね。
毎回removeEventListener
を使うより随分楽ですね。