答案公布
在js开发中,使用addEventListener API为DOM元素绑定事件(比如鼠标事件),当我们在页面
上移除该DOM元素,没有使用removeEventListener解绑事件, 该元素绑定的事件函数就
不会解绑,而且未被js垃圾回收机制回收,依旧占用js内存!
Demo例子验证
啥也不说,先看demo关键代码
<!-- 省略css代码 -->
<div class="box1 flex" id="box1">
Box1
<div class="box2 flex" id="box2">
Box2 <div class="box3 flex" id="box3">Box3</div>
</div>
</div>
<br />
<button onclick="removeNode()">删除Box2,Box3</button>
<br />
<br />
<button onclick="removeNodeEventBox2()">remove Box2的绑定事件</button>
上述代码,展示的页面效果
页面有3个层层嵌套的div,由外到里Box1,Box2, Box3,
给每个div绑定click事件, 代码如下:
let box1 = null
let box2 = null
let box3 = null
window.onload = function() {
box1 = document.getElementById('box1')
box2 = document.getElementById('box2')
box3 = document.getElementById('box3')
/* false 事件冒泡 ture 事件捕获 */
const bl = false
box1.addEventListener('click', fn1, bl )
box2.addEventListener('click', fn2, bl )
box3.addEventListener('click', fn3, bl )
}
/* 事件函数 */
function fn1 () { console.log('box1') }
function fn2 () { console.log('box2') }
function fn3 () { console.log('box3') }
绑定事件成功,点击Box3,触发事件冒泡,控制台显示box3, box2, box3
然后点击'删除Box2,Box3', 执行removeNode 事件, 代码和效果如下
/* 删除Box2,Box3 按钮 执行 */
function removeNode() {
box2.parentNode.removeChild(box2)
setTimeout(() => {
console.log('------删除Box2,Box3, 延时1秒---------')
/* 模拟点击 Box3 */
box3.click()
}, 1000)
}
执行说明:
页面已经成功删除Box2, Box3两个DOM元素,删除成功后,延时1秒执行Box3的click事
件,控制台打印‘box3’ 'box2'。
因此说明使用addEventListener API为DOM元素绑定事件(如鼠标事件),当我们在页面上移
除****该DOM元素, 该元素绑定的事件函数依旧可以执行,事件函数fn2, fn3仍被引用,不会释
放。由于Box2在页面上删除不存在,事件冒泡的链路被打断,所以不会执行Box1的click事件fn1。
如果在删除Box2前,我们使用removeEventListener移除绑定事件, 后执行删除Box2,Box3,代码和效果如下
/* remove Box2的绑定事件 按钮 执行 */
function removeNodeEventBox2() {
box2.removeEventListener('click', fn2 )
}
Box2绑定的事件被移除,Box3绑定的事件没有移除。
总结
addEventListener 和 removeEventListener 在我们开发中经常用来给DOM元素绑定事件,当
我们要在页面document上移除DOM,别忘了先清除其绑定的事件,防止内存泄漏,和产生莫
名其妙的bug。