[Javascript] Avoid frequently adding/removing event listener for a DOM element
It can be a performance bottleneck if you frequently add/remove event listener bind to a DOM element.
patchProps(el, key, prevValue, nextValue) {
if (isOn(key)) {
const eventName = key.slice(2).toLowerCase();
prevValue && el.removeEventListener(eventName, prevValue);
el.addEventListener(eventName, nextValue);
}
...
}
What we can do is bind listener to a variable, and this variable holding the real event handler, instead of add/remove listener, we just set new value for the vairable.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn">
Replace me
</button>
<script>
let invoker = {
value: null,
setValue(fn) {
this.value = fn;
},
run(e) {
this.value(e);
},
};
const btn = document.getElementById("btn");
invoker.setValue(() => {
alert("original value");
});
btn.addEventListener("click", invoker.run.bind(invoker));
setTimeout(() => {
invoker.setValue(() => {
alert("second value");
});
}, 2000);
</script>
</body>
</html>
Code:
patchProps(el, key, prevValue, nextValue) {
if (isOn(key)) {
const eventName = key.slice(2).toLowerCase();
let invoker = el._vei;
if (nextValue) {
if (!invoker) {
invoker = el._vei = (e) => {
invoker.value(e);
};
invoker.value = nextValue;
el.addEventListener(eventName, invoker);
} else {
invoker.value = nextValue;
}
} else {
el.removeEventListener(eventName, invoker);
}
}