EventTarget.removeEventListener() 取消监听事件不起作用(失效)的原因

一.问题产生的原因

没有正确匹配到要删除的事件监听

二.语法介绍

1.监听事件
addEventListener() 语法

target.addEventListener(type, listener[, options])
target.addEventListener(type, listener[, useCapture])

2.取消事件
removeEventListener() 语法

target.removeEventListener(type, listener[, options])
target.removeEventListener(type, listener[, useCapture])

参数说明

  • type: 表示监听事件类型的字符串。
  • listener: 目标事件绑定的回调函数
  • options: 一个指定有关 listener 属性的可选参数对象
  • useCapture: 指定需要移除的 EventListener 函数是否为捕获监听器。true 表示“事件捕获”, 默认为
    false, 表示“事件冒泡”

3. removeEventListener() 移除成功需要满足

  • 需要移除的事件类型必须是一样的, 比如: click

  • 需要从目标事件移除的 EventListener 函数必须和
    addEventListener 中注册的是同一个, 也就是说引用地址是相同的

  • 指定需要移除的 EventListener 函数的useCapture 和 addEventListener 中注册的相同的

4.举例说明

1、设置 useCapture

element.addEventListener("mousedown", handleMouseDown, true);
element.removeEventListener("mousedown", handleMouseDown, false); // 失败
element.removeEventListener("mousedown", handleMouseDown, true); // 成功

2、设置 options

element.addEventListener("mousedown", handleMouseDown, { passive: true });

注意此时的 useCapture 默认为 false, 所以 removeEventListener 也应该设置 useCapture 为 false

element.removeEventListener("mousedown", handleMouseDown, { passive: true }); // 成功
element.removeEventListener("mousedown", handleMouseDown, { capture: false }); // 成功
element.removeEventListener("mousedown", handleMouseDown, { capture: true }); // 失败
element.removeEventListener("mousedown", handleMouseDown, { passive: false }); // 成功
element.removeEventListener("mousedown", handleMouseDown, false); // 成功
element.removeEventListener("mousedown", handleMouseDown, true); // 失败

三.可能遇到的问题

1.使用了匿名函数
这样写是无效的

// index.vue
create (){
  document.addEventListener( "click", function() { console.log("匿名函数, click") }, false );
},

destroyed() {
  // 这样写是无效的
  document.removeEventListener( "click", function() { console.log("匿名函数, click") }, false );
},

需要改成:

// index.vue
create (){
  document.addEventListener( "click", this.callBack, false );
  // 监听生命周期
  // this.$once('hook:destroyed', () => {
      // document.removeEventListener( "click", this.callBack, false );
  // })
},

// 也可以使用上面的方法监听生命周期
destroyed() {
  document.removeEventListener( "click", this.callBack, false );
},

methods: {
  callBack() { console.log("匿名函数, click") };
}

2.忽略了函数的引用地址
这样写是无效的

// index.vue
create (){
  this.eventListener("add");
  this.$once('hook:destroyed', () => {
     this.eventListener("remove");
  })
},

methods: {
  eventListener(val) {
    const callBackFn = () => {
      console.log("函数表达式, click");
    };
    if (val === "add") {
      document.addEventListener("click", callBackFn);
    } else if (val === "remove") {
      document.removeEventListener("click", callBackFn);
    }
  },
}

因为 create() 和 destroyed() 两次的调用分别初始化了一个函数 callBackFn, 这两个 callBackFn 存放在内存中的地址是不一样的, 是两个没有关系的函数, 所以 removeEventListener() 是不起作用(失效)的
同理改成下面这样: 把 callBackFn 提取到一个公共方法中:

// code...
methods: {
  eventListener(val) {
    if (val === "add") {
      document.addEventListener("click", this.callBackFn);
    } else if (val === "remove") {
      document.removeEventListener("click", this.callBackFn);
    }
  },

  callBackFn() {
    console.log("函数表达式, click");
  }
}

归根结底的原因是: 没有正确匹配到要删除的事件监听

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值