深入解析addEventListener三个参数:从基础用法到高级事件控制

1次阅读
没有评论

共计 1793 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

核心概念:三个参数拆解

  1. type(事件类型)
    字符串类型,表示监听的事件名称(如'click''scroll')。注意:
  2. 不要加 on 前缀(错误示例:'onclick'
  3. 大小写敏感('keydown''KeyDown'

    深入解析 addEventListener 三个参数:从基础用法到高级事件控制

  4. listener(回调函数)
    事件触发时执行的函数,可通过 event 参数获取事件对象。关键细节:

  5. 避免使用匿名函数(不利于移除监听)
  6. 箭头函数会改变 this 指向

  7. options/useCapture(控制参数)
    第三参数有两种形式:

  8. 布尔值:控制捕获 / 冒泡阶段(默认 false 即冒泡阶段)
  9. 对象:支持更精细配置(如{passive: true}

痛点分析:那些年我们踩过的坑

  • 内存泄漏:未移除的事件监听导致 DOM 元素无法回收

    // 错误案例
    element.addEventListener('click', () => {console.log('点击后回调依旧存在内存中');
    });

  • 意外的事件冒泡:子元素触发事件影响父元素

    <div id="parent">
      <button id="child"> 点击我触发父元素事件 </button>
    </div>

  • 滚动卡顿 :未使用passive 优化的滚动事件阻塞主线程


技术方案:useCapture vs options 对象

1. 捕获与冒泡阶段控制

// 捕获阶段触发(父→子)document.addEventListener('click', handler, true);

// 冒泡阶段触发(子→父,默认)document.addEventListener('click', handler, false);

2. options 对象高级配置

// 最佳实践组合
element.addEventListener('scroll', handler, {passive: true,    // 告诉浏览器不会调用 preventDefault()
  once: true,       // 只触发一次后自动移除
  capture: false    // 冒泡阶段
});

代码实验室:完整示例

// 事件委托示例(利用冒泡)document.getElementById('list').addEventListener('click', (event) => {if (event.target.tagName === 'LI') {console.log('点击的列表项 ID:', event.target.id);
  }
}, {capture: false});

// 性能敏感场景
window.addEventListener('touchmove', (e) => {// 此处不会调用 e.preventDefault()
}, {passive: true}); // 提升滚动流畅度

// 一次性事件
const modal = document.querySelector('.modal');
modal.addEventListener('animationend', () => {modal.remove();
}, {once: true});

性能考量:实测数据对比

使用 Chrome DevTools 的 Performance 面板测试:

参数配置 滚动事件处理耗时
passive 120ms
{passive: true} 8ms
{capture: true} 无明显差异

避坑指南:5 个高频错误

  1. 匿名函数无法移除
    解决方案:始终使用具名函数引用

  2. 误用 stopPropagation
    替代方案:使用 event.target 精细控制

  3. 重复添加相同监听器
    检测方法:getEventListeners(element)(Chrome 控制台)

  4. 未考虑移动端触摸事件
    必加配置:{passive: true}

  5. SSR hydration 报错
    修复方案:添加事件前检查 DOM 是否存在


优化思路:项目实践建议

  1. 事件委托:在父级监听子元素事件(适合动态内容)
  2. 懒加载监听:IntersectionObserver 替代 scroll 事件
  3. 性能监控 :用Event Timing API 分析事件处理耗时
  4. 清理策略
    // 组件卸载时
    const cleanUp = () => {element.removeEventListener('click', handler);
    };
    // React 示例
    useEffect(() => cleanUp, []);

最后思考:你当前项目中有多少事件监听器可以通过 oncepassive优化?试试在控制台运行 getEventListeners(window) 自查吧!

正文完
 0
评论(没有评论)