在 JavaScript 中,绑定事件主要有**DOM0 级事件处理(onclick 这类)和DOM2 级事件处理(addEventListener)两种方式,前者是早期的简单实现,后者是 W3C 标准的进阶方案。addEventListener 被更推荐,核心原因是它解决了 DOM0 级事件的诸多限制,提供了更灵活、强大的事件处理能力,具体优势如下:

目录

DOM0 级事件处理(onclick 这类)

DOM2 级事件处理(addEventListener)

区别

1. 支持绑定多个同类型事件处理函数

2. 可控制事件的捕获/冒泡阶段

3. 可精准移除事件处理函数

4. 支持自定义事件

5. 更丰富的配置项(现代浏览器)

兼容性说明

表格总结:

OM0 级 vs DOM2 级事件(addEventListener)


在开始讲区别之前,我们要先了解这两种方式的语法:

DOM0 级事件处理(onclick 这类)

1. HTML 内联式绑定(行内事件)

直接在 HTML 标签中通过 on[事件类型] 属性书写执行代码或函数调用,属于 HTML 与 JavaScript 耦合的写法。

<标签名 on[事件类型]="JavaScript 代码/函数调用()">...</标签名>

2. JavaScript 脚本式绑定(推荐)

先获取 DOM 元素,再为元素的 on[事件类型] 属性赋值为函数(匿名函数 / 命名函数),实现 HTML 与 JavaScript 解耦,是更主流的 DOM0 级写法。

// 获取DOM元素
const element = document.getElementById('xxx');
// 绑定事件处理函数
element.on[事件类型] = 处理函数;

DOM2 级事件处理(addEventListener)

addEventListener语法:

element.addEventListener(eventType, handler, [options]);

各部分详细解释:

  • element

要绑定事件的 DOM 元素(如 document、document.body、button)

  • eventType

事件类型名称,不带前缀 on(如点击事件是 click 而非 onclick)。

常见值:click、mouseover、keydown、load、resize、submit 等。

  • handler

(函数 / 对象)事件触发时执行的处理程序,有两种形式:

函数形式:普通函数、匿名函数、箭头函数(注意 this 指向差异)。

对象形式:实现了 handleEvent 方法的对象(较少用)。

  • options / useCapture(可选)

控制事件的触发阶段和行为,是布尔值或配置对象:

布尔值 useCapture:false(默认)表示冒泡阶段触发,true 表示捕获阶段触发。

配置对象 options(更灵活),包含以下属性:

属性

类型

说明

capture

布尔值

同 useCapture,true为捕获阶段触发

once

布尔值

若为 true

,事件触发一次后自动移除该处理程序

passive

布尔值

若为 true

,表示处理程序不会调用 preventDefault()

(优化滚动性能)

signal

AbortSignal

通过 AbortController

手动移除事件监听(现代浏览器支持)


区别

1. 支持绑定多个同类型事件处理函数

DOM0 级的 onxxx 事件是赋值式的,后绑定的函数会直接覆盖之前绑定的同类型函数;

而 addEventListener 可以为同一个元素的同一个事件绑定多个处理函数,且会按照绑定顺序依次执行。

示例对比:

<button id="btn">点击我</button>
<script>
    const btn = document.getElementById('btn');
    // DOM0 级:后赋值的覆盖前一个
    btn.onclick = function() {
        alert('第一个点击事件'); // 不会执行
    };
    btn.onclick = function() {
        alert('第二个点击事件'); // 仅执行这个
    };

    // DOM2 级:多个同类型事件都执行
    btn.addEventListener('click', function() {
        console.log('第一个 addEventListener 事件'); // 先执行
    });
    btn.addEventListener('click', function() {
        console.log('第二个 addEventListener 事件'); // 后执行
    });
</script>

2. 可控制事件的捕获/冒泡阶段

DOM 事件流分为捕获阶段、目标阶段、冒泡阶段三个阶段。addEventListener 的第三个参数可以指定事件在捕获阶段还是冒泡阶段触发,而 DOM0 级的 onxxx 事件只能在冒泡阶段触发,无法控制。

  • 第三个参数为 true:事件在捕获阶段执行;
  • 第三个参数为 false(默认):事件在冒泡阶段执行。

示例:

<div id="parent" style="padding: 20px; background: red;">
    <button id="child">子按钮</button>
</div>
<script>
    const parent = document.getElementById('parent');
    const child = document.getElementById('child');

    // 捕获阶段执行(true)
    parent.addEventListener('click', function() {
        console.log('父元素 捕获阶段');
    }, true);
    // 冒泡阶段执行(false,默认)
    parent.addEventListener('click', function() {
        console.log('父元素 冒泡阶段');
    });
    child.addEventListener('click', function() {
        console.log('子元素 目标阶段');
    });
    // 点击子按钮,输出顺序:父元素 捕获阶段 → 子元素 目标阶段 → 父元素 冒泡阶段
</script>

3. 可精准移除事件处理函数

如果需要取消已绑定的事件,

addEventListener 配合 removeEventListener 可以精准移除指定的事件处理函数;

而 DOM0 级事件只能通过 onxxx = null 清空所有同类型事件,无法单独移除某一个。

语法:element.on[事件类型] = null;

注意:removeEventListener 必须传入与 addEventListener 完全相同的函数引用(不能是匿名函数),否则无法移除。

示例:

<button id="btn">点击我</button>
<script>
    const btn = document.getElementById('btn');
    // 定义具名函数(非匿名)
    function clickHandler() {
        console.log('点击事件被触发');
    }

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

    // 1秒后移除事件
    setTimeout(() => {
        btn.removeEventListener('click', clickHandler);
        console.log('事件已被移除,后续点击无效果');
    }, 1000);

    // DOM0 级移除:只能清空所有同类型事件
    // btn.onclick = null;
</script>

4. 支持自定义事件

addEventListener 可以监听自定义事件(通过 new CustomEvent 创建),而 DOM0 级的 onxxx 仅支持浏览器原生事件(click、load、mouseover 等),无法处理自定义事件。

示例:

<button id="btn">触发自定义事件</button>
<script>
    const btn = document.getElementById('btn');
    // 监听自定义事件
    btn.addEventListener('myCustomEvent', function(e) {
        console.log('自定义事件触发:', e.detail); // 输出:自定义事件触发: 我是自定义数据
    });

    // 点击按钮时触发自定义事件
    btn.addEventListener('click', function() {
        // 创建自定义事件并传递数据
        const customEvent = new CustomEvent('myCustomEvent', {
            detail: '我是自定义数据'
        });
        // 派发事件
        btn.dispatchEvent(customEvent);
    });
</script>

5. 更丰富的配置项(现代浏览器)

现代浏览器中,addEventListener 的第三个参数还可以是一个配置对象,提供更灵活的事件控制:

  • capture: boolean:是否在捕获阶段执行(同布尔值参数);
  • once: boolean:事件仅执行一次后自动移除;
  • passive: boolean:声明事件处理函数不会调用 preventDefault(),用于提升滚动、触摸等事件的性能(如移动端滚动卡顿问题)。

示例(仅执行一次的事件):

<button id="btn">仅点击一次有效</button>
<script>
    const btn = document.getElementById('btn');
    btn.addEventListener('click', function() {
        alert('仅执行一次');
    }, { once: true }); // 事件执行一次后自动移除
</script>

兼容性说明

addEventListener 是 W3C 标准,IE9 及以上的现代浏览器均支持;早期 IE8 及以下使用非标准的 attachEvent/detachEvent,但目前前端开发中已基本无需兼容这些老旧浏览器。

综上,addEventListener 在灵活性、功能性、标准性上都远优于 DOM0 级的 onxxx 事件,因此成为实际开发中的首选方案。

表格总结:

OM0 级 vs DOM2 级事件(addEventListener)

特性

DOM0 级事件

DOM2 级事件(addEventListener

)

绑定数量

一个事件类型仅能绑定一个函数

一个事件类型可绑定多个函数

事件阶段

仅支持冒泡阶段

支持冒泡 / 捕获阶段

移除方式

赋值为 null

调用 removeEventListener

配置项

无

支持 once/passive/signal

等

兼容性

所有浏览器支持

IE8 及以下不支持(需用 attachEvent)

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐