JavaScript DOM 原生部分(五):事件绑定

文章目录

在 JavaScript 中, 事件绑定 是实现页面交互的核心,指将事件处理函数与 DOM 元素的特定事件(如点击、鼠标移动、键盘输入)关联,当事件触发时执行对应逻辑.且原生方式包含 传统绑定事件监听事件委托 等不同模式,以下详细讲解:

原生 JS 提供了三种主流的事件绑定方式,各有适用场景和特点.

一.传统事件绑定(内联绑定/属性绑定)

这是最基础的绑定方式,分为HTML 内联绑定DOM 属性绑定 ,本质是将事件处理函数赋值给元素的事件属性(如 onclickonmouseover).

1.HTML 内联绑定(不推荐,结构与行为耦合)

直接在 HTML 标签中通过 on+事件名 属性绑定函数,适合简单测试,不利于代码维护.

html 复制代码
<!-- HTML 内联绑定点击事件 -->
<button onclick="handleClick()">点击我</button>

<script>
  function handleClick() {
    alert('按钮被点击了!');
  }
</script>

2.DOM 属性绑定(简单场景可用)

通过 JS 直接给元素的事件属性赋值,优点是简单直观,缺点是一个事件只能绑定一个处理函数(后续赋值会覆盖之前的).

javascript 复制代码
// HTML: <button id="btn">点击我</button>
const btn = document.getElementById('btn');

// 绑定点击事件
btn.onclick = function () {
  console.log('按钮被点击(属性绑定)');
};

// 后续赋值会覆盖原有事件处理函数
btn.onclick = function () {
  console.log('新的点击事件(覆盖了之前的)');
};

// 移除事件: 赋值为 null
btn.onclick = null;

二.事件监听方式(addEventListener,推荐)

这是 W3C 标准 的事件绑定方式,也是现代开发中最常用的方式,支持一个事件绑定多个处理函数,还能指定事件传播模式.

1.基本语法

javascript 复制代码
element.addEventListener(事件名, 处理函数, 可选参数);
  • 事件名 : 不带 on 前缀(如 click 而非 onclickmouseover 而非 onmouseover).
  • 处理函数: 事件触发时执行的函数(普通函数或箭头函数).
  • 可选参数 :
    • 布尔值: true 表示事件捕获 ,false(默认)表示事件冒泡.
    • 配置对象: 如 { capture: false, once: true, passive: true },其中:
      • once: true: 事件只触发一次,触发后自动移除监听.
      • passive: true: 表示处理函数不会调用 event.preventDefault()(优化移动端滚动性能).

2.基本使用

javascript 复制代码
const btn = document.getElementById('btn');

// 绑定第一个点击事件处理函数
btn.addEventListener('click', function () {
  console.log('第一个点击处理函数');
});

// 绑定第二个点击事件处理函数(不会被覆盖)
btn.addEventListener('click', () => {
  console.log('第二个点击处理函数');
});

// 绑定一次性事件(仅触发一次)
btn.addEventListener(
  'click',
  function () {
    console.log('这个事件只触发一次');
  },
  { once: true }
);

3.移除事件监听(removeEventListenera)

需注意: 移除的处理函数必须与绑定的是同一个引用(匿名函数无法被移除).

javascript 复制代码
// 定义具名函数(便于移除)
function handleClick() {
  console.log('可被移除的点击事件');
}

// 绑定事件
btn.addEventListener('click', handleClick);

// 移除事件(必须传相同的函数引用)
btn.removeEventListener('click', handleClick);

4.事件传播模式

DOM 事件流分为三个阶段: 事件捕获阶段目标阶段事件冒泡阶段.

  • 事件冒泡(默认): 事件从触发的目标元素向上传播到祖先元素(如点击子元素,父元素的同事件也会触发).
  • 事件捕获: 事件从祖先元素向下传播到目标元素.
javascript 复制代码
// HTML: <div id="parent"><button id="btn">点击</button></div>
const parent = document.getElementById('parent');
const btn = document.getElementById('btn');

// 父元素捕获阶段监听
parent.addEventListener('click', () => console.log('父元素捕获'), true);
// 子元素冒泡阶段监听
btn.addEventListener('click', () => console.log('子元素冒泡'), false);
// 父元素冒泡阶段监听
parent.addEventListener('click', () => console.log('父元素冒泡'), false);

// 点击按钮的执行顺序: 父元素捕获 → 子元素冒泡 → 父元素冒泡

三.常用事件类型

事件类别 常见事件 触发场景
鼠标事件 clickdblclickmouseovermouseoutmousedownmouseup 点击、双击、鼠标 移入 / 移出 等
键盘事件 keydownkeyupkeypress 键盘 按下 / 松开
表单事件 submitchangeinputfocusblur 表单提交、值变化、输入等
文档 / 窗口事件 DOMContentLoadedloadresizescroll DOM 加载完成、页面加载完成等

四.事件对象(event)

当事件触发时,会自动传入一个事件对象 (event),包含事件的相关信息和常用方法,是处理事件的重要工具.

常用属性/方法 作用
event.target 触发事件的实际目标元素(事件委托的核心)
event.currentTarget 绑定事件的当前元素 (等同于 this)
event.type 事件类型(如 clickinput)
event.preventDefault() 阻止事件的默认行为(如阻止表单提交、链接跳转)
event.stopPropagation() 阻止事件冒泡或捕获
event.stopImmediatePropagation() 阻止事件传播,且阻止当前元素的后续事件处理函数执行
event.key 键盘事件中按下的键(如 Entera)
event.clientX/clientY 鼠标事件中鼠标的坐标(相对于视口)

常用事件绑定表

场景 推荐方法
简单事件绑定(单个函数) element.onclick = fn(简单场景)/ addEventListener
多个事件处理函数 addEventListener
事件委托 祖先元素 addEventListener + event.target 判断
一次性事件 addEventListener{ once: true }

注意事项

  1. this 的指向问题

    • 原生 addEventListener 中,处理函数的 this 指向绑定事件的元素 ;箭头函数的 this 指向定义时的上下文(如全局 window).
  2. 事件冒泡的控制

    • 不必要的事件冒泡可能导致意外的事件触发,可通过 event.stopPropagation() 阻止.
    • 表单提交、链接跳转等默认行为,需用 event.preventDefault() 阻止.
  3. 动态元素的事件绑定

    • 动态添加的 DOM 元素,无法通过普通事件绑定生效,必须使用事件委托.
  4. 性能优化

    • 避免给大量元素单独绑定事件,优先使用事件委托.
    • 移除不再需要的事件监听(如页面卸载、组件销毁时),防止内存泄漏.
  5. 浏览器兼容

    • 旧版 IE(IE8 及以下)不支持 addEventListener,需使用 attachEvent()(如 element.attachEvent('onclick', fn)),但现代开发中可忽略(或通过 Babel/Polyfill 兼容).

总结

  • 原生 JavaScript 中,addEventListener 是最灵活的事件绑定方式,事件委托是处理大量元素和动态元素的最优解.
  • 掌握事件对象的使用、事件传播的控制和事件委托的技巧,是实现高效、稳定页面交互的核心.
相关推荐
出来吧皮卡丘2 小时前
A2UI:让 AI Agent 自主构建用户界面的新范式
前端·人工智能·aigc
Jeking2172 小时前
进阶流程图绘制工具 Unione Flow Editor-- 击破样式痛点:全维度自定义解决方案
前端·流程图·workflow·unione flow·flow editor·unione cloud
晴转多云5432 小时前
关于Vite后台项目的打包优化(首屏加载)
前端
lly2024062 小时前
Redis 发布订阅
开发语言
A0_張張2 小时前
记录一个PDF盖章工具(PyQt5 + PyMuPDF)
开发语言·python·qt·pdf
巴拉巴拉~~2 小时前
Flutter 通用下拉选择组件 CommonDropdown:单选 + 搜索 + 自定义样式
开发语言·javascript·ecmascript
阿苟2 小时前
nginx部署踩坑
前端·后端
ZHang......2 小时前
LeetCode 1114. 按序打印
java·开发语言·算法
小林攻城狮2 小时前
pdfmake 生成平铺式水印:核心方法与优化
前端