错误删除事件
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() {
// 每次触发事件都调函数
// 方式1
this.ev = _ => this.changeEv()
// 方式2
this.docEvFun = function (e) {
return this.changeEv(e)
}
}
addEv() {
// 添加mousemove事件
//调用方式1
document.addEventListener('mousemove', this.ev)
//调用方式2
//document.addEventListener('mouseup', this.docEvFun(ev))//可注销
}
changeEv(ev) {
console.log('触发事件', this)
// 删除mousemove事件 方式1
document.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)//false
const 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 辑