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

窗口缩小至960px以下时无法移除Event Listener的问题求助

窗口缩小至960px以下时无法移除Event Listener的问题求助

问题核心原因

我一眼就定位到问题所在了:你把dropopen和dropclose定义在了bindIt函数的内部!

每次触发load或者resize事件时,bindIt都会被重新执行一遍,这时候函数内部的dropopen和dropclose会被重新创建成全新的函数实例——也就是说,第一次窗口大于960px时添加的事件监听器,对应的是第一次bindIt执行时创建的那两个函数;而当你缩小窗口触发resize、再次执行bindIt时,你用新创建的dropopen/dropclose去调用removeEventListener,这两个新函数和之前添加的完全不是同一个引用,浏览器自然找不到要移除的事件监听器,所以移除操作直接失效了。

另外还有个隐藏问题:每次窗口大于960px时,bindIt都会重复添加事件监听器,导致鼠标事件触发时dropopen/dropclose会被执行多次,哪怕后续能成功移除,也得移除多次才能清干净。

修复方案

最直接的解决办法是把dropopen和dropclose移到bindIt函数外面,让它们成为固定的全局(或外层作用域)函数,这样每次add/remove操作的都是同一个函数引用:

// 把这两个函数移到bindIt外面,确保引用固定不变
function dropopen() {
  var attribute = this.getAttribute("group");
  if (this.querySelector('#' + attribute) != null) {
    document.getElementById(attribute).style.display = 'block';
  }
}

function dropclose() {
  var attribute = this.getAttribute("group");
  if (this.querySelector('#' + attribute) != null) {
    document.getElementById(attribute).style.display = 'none';
  }
}

window.addEventListener("load", function() { bindIt(); });
window.addEventListener("resize", function() { bindIt(); });

function bindIt() {
  var elements = document.getElementsByClassName("DropMenu");
  
  // 优化:先统一移除事件监听器,避免重复添加
  for (var i = 0; i < elements.length; i++) {
    elements[i].removeEventListener('mouseover', dropopen, false);
    elements[i].removeEventListener('mouseout', dropclose, false);
  }
  
  if (window.innerWidth > 960) {
    for (var i = 0; i < elements.length; i++) {
      elements[i].addEventListener('mouseover', dropopen, false);
      elements[i].addEventListener('mouseout', dropclose, false);
    }
  }
}

额外优化建议

  1. 合并循环操作:像上面的代码那样,把移除和添加的循环合并,减少DOM操作次数,提升性能。
  2. 使用事件委托替代逐个绑定:如果你的下拉菜单结构固定,可以考虑用事件委托,只在父元素上绑定一次事件,根据事件源判断是否触发下拉逻辑,这样就不用每次resize都去操作多个元素的事件监听器了。
  3. 防抖处理resize事件:resize事件触发频率很高,建议加个防抖函数,避免bindIt被频繁调用,比如:
function debounce(func, delay = 200) {
  let timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(func, delay);
  }
}

// 用防抖后的函数绑定resize事件
window.addEventListener("resize", debounce(bindIt));

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 08:13:10