如何正确地添加和删除 DOM 元素事件
浏览器的 JavaScript 最大的作用就是让原本静态的、无聊的页面,变成有趣的、可以活动的、有交互能力的页面,而要实现与用户互动的能力就不得不使用浏览器的事件函数,有了它,你的页面就能响应用户的操作。虽然添加事件是很简单的事情,但想要加得好、加得妙,那还得下翻功夫。
添加事件的方法
除去兼容性不说,目前主要有两种添加事件的方法,下面以添加“点击”事件为例:
// 要添加事件的DOM元素
const element = document.querySelector('.element');
// addEventListener
element.addEventListener('click', () => console.log('click'));
// onclick
element.onclick = () => console.log('click');
这两种方法虽然都能添加“点击”事件,并且执行起来并没什么不同,但是addEventListener
是可以添加重复的“点击”事件,而且可以切换“捕抓”或者“冒泡”模式,而onclick
只能添加一个“点击”事件,而且只能是“冒泡”模式。(如果对“捕抓”和“冒泡”模式不了解,请看这里:DOM事件传递顺序)
看下面代码,当用户点击element
元素时,会输出什么?
// 多次添加
// addEventListener
element.addEventListener('click', () => console.log('click1'));
element.addEventListener('click', () => console.log('click2'));
// onclick
element.onclick = () => console.log('click3');
element.onclick = () => console.log('click4');
最终输出的是:click1
, click2
, click4
。我们要牢记addEventListener
可以重复添加相同事件的特性,小心添加了多余的事件。也要小心onclick
只能添加一次,不要把别人的事件覆盖掉了哦。
同类型事件触发顺序
如果在一个元素上添加了相同事件,并且传递模式都一样,例如都是冒泡,当触发该元素事件时,它就会按照添加的顺序执行,无论是addEventListener
还是onclick
方法。但假如你希望在执行某个事件回调后,不再执行别的事件函数,你可以使用event.stopPropagation
方法。
// addEventListener
element.addEventListener('click', () => console.log('click1'));
element.addEventListener('click', (event) =>{
// 停止事件传递
event.stopPropagation();
console.log('click2')
});
element.addEventListener('click', () => console.log('click3'));
这里会输出click1
, click2
,最后那个事件会被阻止触发。要注意的是,event.stopPropation
只能阻止顺序之后的事件,并且只能阻止同类型事件,也不会阻止元素的默认事件(要阻止默认事件,还得另外使用event.preventDefault
,不要搞混了哦)。
删除事件
为了防止内存浪费或者避免干扰用户,我们需要把不再使用的事件去除,但去除事件并不容易,需要细心操作。
去除事件有个基本原则,就是怎么来就怎么去。如果你用的是addEventListener
添加的事件,那么你也要用addEventListener
来删除:
// “点击”事件的参数
const option = { passive: true };
// “点击”事件的回调
const callback = () => console.log('click');
// 添加
element.addEventListener('click', callback, option);
// 删除
element.removeEventListener('click', callback, option)
上面的代码里,不仅addEventListener
要对应上removeEventListener
,连事件回调函数,还有option
参都都要对应上,缺一不同,所以平时要留意,千万不要漏了哦。
相对来说,onclick
就简单多了:
// 添加事件
element.onclick = () => console.log('click');
// 删除事件
element.onclick = null;
不需要任何对应值,直接赋值null
即可。
总结
我们在使用某些框架时,例如Vue,一定要提防事件多次添加的问题,千万不能在watch
或computed
的地方使用addEventListener
,很容易造成内存泄漏和其它不可预知的问题。就算在mounted
组件创建函数里使用,也要提访组件多次创建的问题,总之要时该保持清醒,别搞错了哦。