event对象

6 阅读4分钟

一、Event 对象的核心概念

  • 定义:浏览器或Node.js中表示事件状态的对象,包含事件发生时的所有相关信息。
  • 作用:在事件处理函数中传递事件细节(如触发元素、鼠标位置、键盘按键等)。
  • 分类
    • 浏览器DOM事件:如clickkeydownsubmit
    • 自定义事件:通过Event/CustomEvent创建的用户自定义事件。
    • Node.js事件:如fs.readFiledata事件、http服务器的request事件。

二、浏览器DOM事件对象(重点)

1. 基础属性与方法(高频)
// 事件处理函数中的event对象示例
document.addEventListener('click', (event) => {
  // 事件目标与类型
  console.log(event.target);       // 触发事件的元素
  console.log(event.currentTarget); // 绑定事件的元素
  console.log(event.type);         // 事件类型('click')
  
  // 鼠标事件特有属性
  console.log(event.clientX);      // 鼠标在视口的X坐标
  console.log(event.pageY);        // 鼠标在页面的Y坐标
  console.log(event.button);       // 鼠标按键(0=左键,1=中键,2=右键)
  
  // 键盘事件特有属性
  if (event.type === 'keydown') {
    console.log(event.key);        // 按下的键名('Enter'/'a')
    console.log(event.keyCode);    // 按键编码(旧标准,如Enter=13)
    console.log(event.ctrlKey);    // Ctrl键是否按下(布尔值)
  }
  
  // 事件控制方法
  event.preventDefault(); // 阻止默认行为(如链接跳转、表单提交)
  event.stopPropagation(); // 阻止事件冒泡
});
2. 核心属性解析
  • 事件目标相关
    • target:实际触发事件的元素(如点击按钮内的图标,target是图标元素)。
    • currentTarget:事件绑定的元素(如给按钮绑定事件,currentTarget是按钮)。
  • 坐标相关
    • clientX/clientY:鼠标相对于浏览器视口的坐标。
    • pageX/pageY:鼠标相对于整个文档的坐标(包含滚动偏移)。
    • screenX/screenY:鼠标相对于屏幕的坐标。
  • 交互状态相关
    • shiftKey/ctrlKey/altKey/metaKey:修饰键是否按下(布尔值)。
    • button:鼠标按键编号(常用于区分左右键点击)。
3. 事件控制方法
  • preventDefault()
    • 用途:阻止事件的默认行为(如链接点击跳转、表单提交)。
    • 示例:
      // 阻止链接跳转
      const link = document.querySelector('a');
      link.addEventListener('click', (e) => {
        e.preventDefault();
        console.log('点击被拦截,不跳转');
      });
      
  • stopPropagation()
    • 用途:阻止事件冒泡(如点击子元素时不触发父元素的事件)。
    • 示例:
      <div id="parent">
        <button id="child">点击我</button>
      </div>
      
      document.getElementById('parent').addEventListener('click', () => {
        console.log('父元素被点击');
      });
      document.getElementById('child').addEventListener('click', (e) => {
        e.stopPropagation(); // 阻止冒泡到父元素
        console.log('子元素被点击');
      });
      
  • stopImmediatePropagation()
    • stopPropagation()更严格,阻止同一元素上后续事件监听器的执行。

三、不同场景的Event对象差异

1. 常见事件类型的特有属性
事件类型特有属性示例用途说明
click(鼠标)button, clientX, clientY鼠标按键和位置
keydown(键盘)key, keyCode, charCode按键信息
submit(表单)target.elements表单所有输入元素
mousemove(鼠标移动)movementX, movementY相对于上一次移动的坐标差
input(输入)data, target.value输入的内容
2. 浏览器与Node.js事件对象的区别
  • 浏览器DOM事件
    • 继承自Event接口,包含DOM元素相关属性(如target)。
    • 支持事件冒泡和捕获机制。
  • Node.js事件
    • EventEmitter类生成,属性更灵活(如HTTP请求事件包含req.methodreq.url)。
    • 无冒泡机制,通过on/once绑定事件监听器。
    • 示例(Node.js HTTP服务器):
      const http = require('http');
      const server = http.createServer((req, res) => {
        // req是事件对象,包含HTTP请求信息
        console.log(req.method);  // 'GET'/'POST'等
        console.log(req.url);      // 请求路径
        // ...
      });
      

四、自定义事件(CustomEvent)

1. 创建与分发自定义事件
// 1. 创建自定义事件
const myEvent = new CustomEvent('dataLoaded', {
  detail: {
    data: [1, 2, 3],
    timestamp: new Date()
  },
  bubbles: true,  // 是否冒泡
  cancelable: false // 是否可取消默认行为
});

// 2. 绑定事件监听器
document.addEventListener('dataLoaded', (event) => {
  console.log('接收到自定义事件数据:', event.detail.data);
});

// 3. 分发事件
document.dispatchEvent(myEvent);
2. 应用场景
  • 组件通信:在不直接耦合的组件间传递数据(如父子组件非嵌套时)。
  • 状态通知:数据加载完成、表单验证通过等场景的全局通知。
  • 解耦逻辑:将复杂流程拆分为事件驱动的模块(如状态管理库的设计)。

五、事件委托与Event对象优化(面试加分项)

1. 事件委托原理
  • 核心思想:将事件监听器绑定到父元素,通过event.target判断实际触发的子元素。
  • 示例(优化列表项点击事件)
    // 错误做法:给每个li单独绑定事件(性能差)
    document.querySelectorAll('li').forEach(li => {
      li.addEventListener('click', handleClick);
    });
    
    // 正确做法:事件委托到父元素
    const list = document.querySelector('ul');
    list.addEventListener('click', (event) => {
      if (event.target.tagName === 'LI') {
        const id = event.target.dataset.id;
        handleClick(id);
      }
    });
    
2. Event对象的性能注意点
  • 事件对象池
    • 浏览器会复用Event对象以减少内存分配(如event参数在回调中是同一个实例)。
    • 避免异步操作中保存event对象(可能被后续事件覆盖)。
  • 内存泄漏风险
    • 移除事件监听器时,确保使用相同的回调函数(如用箭头函数会导致无法正确移除)。
    • 示例(错误写法):
      element.addEventListener('click', () => {}); // 箭头函数无法通过removeEventListener移除
      
    • 正确写法:
      const handler = () => {};
      element.addEventListener('click', handler);
      element.removeEventListener('click', handler);