You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止document绑定的keydown事件监听器触发重复事件?

问题原因

你当前绑定在document全局对象上的事件监听器不会随组件销毁自动清除,导航离开页面时旧监听器一直挂载,每次重新进入页面mounted执行时又新增一个监听器,就会出现事件多次触发的问题。你之前的移除逻辑未生效,大概率是添加和移除监听器时传入的函数引用不一致,导致旧监听器没有被正确删掉。

解决方案

1. 固定监听器函数引用

提前将绑定好组件实例this的监听器函数存起来,不要每次调用bind生成新的函数引用,保证移除和添加的是同一个函数。

2. 组件销毁时主动清理全局监听器

在组件卸载生命周期中手动移除绑定在document上的监听器,从根源避免残留。

完整代码示例(Vue2为例,Vue3替换beforeDestroy为beforeUnmount即可)

export default {
  data() {
    return {
      // 其他现有数据...
      boundKeydownListener: null // 存储固定的监听器引用
    }
  },
  mounted() {
    this.setupInputListener();
  },
  // 组件销毁前清理全局监听器
  beforeDestroy() {
    if (this.boundKeydownListener) {
      document.removeEventListener('keydown', this.boundKeydownListener);
    }
  },
  methods: {
    // 补充event形参,避免直接从全局window拿事件对象
    keydownListener(event) {
      const action = handleKeyDown(event.key);
      if (action) {
        this.SEND_INPUT({
          gameId: this.gameId,
          action: action
        });
      }
    },
    setupInputListener() {
      // 只绑定一次this,生成固定引用
      this.boundKeydownListener = this.keydownListener.bind(this);
      // 先移除已有监听器
      document.removeEventListener('keydown', this.boundKeydownListener);
      document.addEventListener('keydown', this.boundKeydownListener);
    }
  }
}

注意事项

  • 不要直接在addEventListener参数里写this.keydownListener.bind(this),每次bind调用都会返回全新的函数实例,后续removeEventListener传入的引用和添加时不一致,会导致移除失败。
  • 所有绑定在window、document这类全局对象上的事件、定时器等副作用,都需要在组件销毁时手动清理,否则会出现内存泄漏、事件重复触发等问题。

内容的提问来源于stack exchange,提问作者hipsterstomper69

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:36:02