【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() {
    
    
    // 每次触发事件都调函数
    // 方式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)
  }
}



结论

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

运行结果
在这里插入图片描述

  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 辑

猜你喜欢

转载自blog.csdn.net/qq_43614372/article/details/130235170