Chrome拡張機能を開発中にもともとのホームページに設定されている、マウスオーバーで動作するイベントを削除したくなった。

クリックされた要素だけでなく、その親要素に設定されているイベントもすべて呼ばれる(伝播する)ことも知っておくべき事柄。

removeEventListener

検索すると一番出てくるのがこれ、第一引数にイベント名、第二引数にその関数。

let button = document.getElementById("hoge");
let action = () => {
    console.log("hello");
}
button.addEventListener('click', action);
button.removeEventListener('click', action);

しかし問題もたくさんあって、onclickで設定したイベントには効果がなく、また無名関数をイベントに設定していたり、別のJSファイルに記述していたためにその関数にアクセスできないという場合には使えない。

let button = document.getElementById("hoge");
let action = () => {
    console.log("hello");
}
button.onclick = action;
button.removeEventListener('click', action);//削除されない

onclickを上書き

onclickでアクションを設定していた場合のみ削除できる。親要素に設定されたイベントは呼ばれる。

let button = document.getElementById("hoge");
button.onclick = () =>{
    console.log("hello");//表示されない
}
button.addEventListener('click', () => {
    console.log("hello2");//表示される
});
button.onclick = () =>{
    return false;
}

removeAttribute

htmlタグに直接記述した場合のみ有効。

<button id="hoge" onclick="action()">test</button>
<script>
    function action(){
        console.log("hello");
    }
    let button = document.getElementById("hoge");
    button.removeAttribute("onclick");
</script>

preventDefault, stopPropagation

子要素に設定することで、親要素のイベントを回避できる。

<div id="bar">
<button id="hoge" onclick="action()">test</button>
</div>
<script>
function action(){
	console.log("hello1");
}
let button = document.getElementById("hoge");
let wrapper = document.getElementById("bar");
button.onclick = () => {
	console.log("hello2");
}
wrapper.onclick = () => {
	console.log("hello3");
}
button.addEventListener('click', (event) => {
	console.log("hello4");//これだけ呼ばれる。
});
button.onclick = (event) => {
	event.preventDefault();
	event.stopPropagation();
};
</script>

addEventListenerに設定した場合はonclickで設定したイベントも呼ばれてしまう。

<div id="bar">
<button id="hoge" onclick="action()">test</button>
</div>
<script>
function action(){
	console.log("hello1");
}
let button = document.getElementById("hoge");
let wrapper = document.getElementById("bar");
button.onclick = () => {
	console.log("hello2");//呼ばれる
}
wrapper.onclick = () => {
	console.log("hello3");
}
button.addEventListener('click', (event) => {
	console.log("hello4");//呼ばれる
});
button.addEventListener('click', (event) => {
	event.preventDefault();
	event.stopPropagation();
});
</script>

まとめ

部分的に削除できる方法は存在するものの、一発できれいに一掃する方法はないみたい。削除して、新しく作った要素を挿入したほうが早いかも。