> 文章列表 > 【JS】Es6无法注销事件 | class构造函数里无法注销事件解决方法(亲测有效)

【JS】Es6无法注销事件 | class构造函数里无法注销事件解决方法(亲测有效)

【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))//错误三}
} 

错误一 、错误二效果图

【JS】Es6无法注销事件 | class构造函数里无法注销事件解决方法(亲测有效)

错误三效果图

【JS】Es6无法注销事件 | class构造函数里无法注销事件解决方法(亲测有效)




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)}
}



结论

  1. 每次添加事件时,都会创建一个全新的回调函数,重点是全新
  2. 若不用一个变量存储回调函数,每次触发事件的回调函数都会不一样,例如:
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

运行结果
【JS】Es6无法注销事件 | class构造函数里无法注销事件解决方法(亲测有效)

  1. 因此,在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 辑