【JS】Es6无法注销事件 | class构造函数里无法注销事件解决方法(亲测有效)
错误删除事件
class Goods {addEv() {// 添加mousemove事件// document.addEventListener('mousemove', this.changeEv.bind(document)) //错误一// document.addEventListener('mousemove', this.changeEv) //错误二document.addEventListener('mousemove', this.changeEv.bind(this)) //错误三}changeEv() {console.log('触发事件', this)// 删除mousemove事件// document.removeEventListener('mousemove', this.changeEv.bind(document)) //错误一// document.addEventListener('mousemove', this.changeEv)//错误二document.removeEventListener('mousemove', this.changeEv.bind(this))//错误三}
}
错误一 、错误二效果图
错误三效果图
2种正确删除事件方式
- 利用一个变量或数组储存要执行的函数,且这个变量或数组元素返回一个函数。
方式1 -> 箭头函数:this会指向父级,不改变this。
方式2 -> 普通函数:先执行一次函数,再返回一个函数也可实现删除事件
代码演示
class Goods {constructor() {// 每次触发事件都调函数// 方式1this.ev = _ => this.changeEv()// 方式2this.docEvFun = function (e) {return this.changeEv(e)}}addEv() {// 添加mousemove事件 //调用方式1document.addEventListener('mousemove', this.ev)//调用方式2//document.addEventListener('mouseup', this.docEvFun(ev))//可注销 }changeEv(ev) {console.log('触发事件', this)// 删除mousemove事件 方式1document.removeEventListener('mousemove', this.ev)// 删除mousemove事件 方式2// document.removeEventListener('mousemove', this.docEvFun)}
}
结论
- 每次添加事件时,都会创建一个全新的回调函数,重点是全新。
- 若不用一个变量存储回调函数,每次触发事件的回调函数都会不一样,例如:
const foo1 = () => ev => () => { console.log('bar') }
const foo2 = () => ev => () => { console.log('bar') }
console.log(foo1 === foo2)//falseconst foo3 = (ev => () => { console.log('bar') }) === (ev => () => { console.log('bar') })
console.log(foo3)//false
运行结果
- 因此,在class面向对象里注销事件时,必须用变量存储一个函数,且存储的这个变量返回一个函数。如:
class Foo {constructor() {// this.ev变量会返回this.changeEv(e)this.ev = e => {return this.changeEv(e)}}changeEv(e) {console.log(e)}
}
有了this.ev就可以在其它地方注销事件,例如:
class Foo {constructor() {// this.ev变量会返回this.changeEv(e)this.ev = e => {return this.changeEv(e)}}addEv() {document.addEventListener('mousemove', this.ev)}changeEv(e) {console.log(e)// 删除mousemove事件 document.removeEventListener('mousemove', this.ev)}
}
箭头函数 与 普通函数增删事件例子
箭头函数
class Foo {constructor() {/* 每次增加事件都会执行this.ev* this.ev 变量会返回this.changeEv(e)函数* 在删除事件时,直接删this.ev即可*/this.ev = e => {return this.changeEv(e)}}addEv() {// 增加事件document.addEventListener('mousemove', this.ev)}changeEv(e) {console.log(e)// 删除事件document.removeEventListener('mousemove', this.ev)}
}
普通函数
class Bar{constructor() {/* 每次增加事件都会执行this.ev* this.ev 变量会返回this.changeEv(e)函数* 在删除事件时,直接删this.ev即可*/this.ev = function (e) {return this.changeEv(e)}}addEv() {/* 增加事件,重点要调用 * 是this.ev() * 而不是this.ev*/document.addEventListener('mousemove', this.ev(e))}changeEv(e) {console.log(e)// 删除事件,直接删this.ev即可document.removeEventListener('mousemove', this.ev)}
}
数组
class Me {constructor() {this.evArr = []}start() {this.evArr.push(e => console.log('你好'))document.addEventListener('mousemove', this.evArr[this.evArr.length - 1])}end() {this.removeAllEv()}removeAllEv() {// 删除所有事件this.evArr.forEach(evItemCallback => {document.removeEventListener('mousemove', evItemCallback)})}}
2023/4/19 9:49 辑