addEventListener、dispatchEvent、removeEventListener
addEventListener
介绍
EventTarget.addEventListener() 方法将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。事件目标可以是一个文档上的元素 Element、Document 和 Window,也可以是任何支持事件的对象(比如 XMLHttpRequest),IE9 以下中为 attachEvent 替代。
推荐使用 addEventListener() 来注册一个事件监听器,理由如下:
- 它允许为一个事件添加多个监听器。
- 它提供了一种更精细的手段来控制 listener 的触发阶段(即可以选择捕获或者冒泡)。
- 它对任何事件都有效,而不仅仅是 HTML 或 SVG 元素。
语法
- addEventListener(type, listener);
- addEventListener(type, listener, options);
- addEventListener(type, listener, useCapture);
返回值:无(undefined)
参数
type: 事件名称,大小写敏感,不含“on”,比如“click”、“mouseover”、“keydown”等
listener: listener 必须是一个实现了 EventListener 接口的对象,或者是一个函数。
options 可选: 一个指定有关 listener 属性的可选参数对象。可用的选项如下:
capture 可选 :布尔值,表示 listener 会在当前事件捕获阶段传播到该 EventTarget 时触发。默认值为 false。
once 可选:布尔值,表示 listener 在添加之后最多只调用一次。如果为 true,listener 会在其被调用之后自动移除。默认值为 false。
passive 可选:布尔值,设置为 true 时,表示 listener 永远不会调用 preventDefault()。如果设置false,同时用户在事件(touchstart/touchmove/touchend,是否还有其他事件未测试)中没有设置 event.preventDefault(),客户端将会忽略它并抛出一个控制台警告。默认值为 false。
signal 可选:AbortSignal,该 AbortSignal 的 abort() 方法被调用时,监听器会被移除。默认值为 false。
useCapture 可选: 布尔值,true 是事件捕获,false 是事件冒泡,默认false。表示在 DOM 树中注册了 listener 的元素,是否要先于它下面的 EventTarget 调用该 listener。当 useCapture(设为 true)时,沿着 DOM 树向上冒泡的事件不会触发 listener。当一个元素嵌套了另一个元素,并且两个元素都对同一事件注册了一个处理函数时,所发生的事件冒泡和事件捕获是两种不同的事件传播方式。事件传播模式决定了元素以哪个顺序接收事件。
useCapture 触发顺序:
true 的触发顺序总是在 false 之前;捕获(true)阶段的事件监听器会在任何非捕获(false)阶段的事件监听器之前被调用。
如果多个均为 true,则外层的触发先于内层;
如果多个均为 false,则内层的触发先于外层。
注意,不适用于 IE。
addEventListener-事件流,分为三个阶段
捕获阶段: 从根节点开始顺序而下,检测每个节点是否注册了事件处理程序。如果注册了事件处理程序,并且 useCapture 为 true,则调用该事件处理程序。(IE 中无此阶段。)
目标阶段: 触发在目标对象本身注册的事件处理程序,也称正常事件派发阶段。
冒泡阶段: 从目标节点到根节点,检测每个节点是否注册了事件处理程序,如果注册了事件处理程序,并且 useCapture 为 false,则调用该事件处理程序。
多个事件示例
<button id="myBtn">Event</button> <script> var btn = document.getElementById("myBtn"); btn.addEventListener("click", function () { alert(this.id); }, false); btn.addEventListener("click", function () { alert("Hello World"); }, false); </script>
建议写法
var btn = document.getElementById("myBtn"); //通过addEventListener()添加的匿名函数无法移除 btn.addEventListener("click", function () { alert(this.id); }, false); btn.removeEventListener("click", function () { //无效! alert(this.id); }, false); //removeEventListener无法删除addEventListener所追加的事件,因为两个方法(匿名)并不相等,内存地址已经是不同的 var handler = function () { alert(this.id); }; btn.addEventListener("click", handler, false); btn.removeEventListener("click", handler, false); //有效!
一旦事件绑定之后,该绑定代码作用域的变量就都保留下来,不会被 JavaScript 引擎回收,这可能会引起占用大量内存的问题,由于 removeEventListener 无法删除匿名函数的事件处理程序,只有在物件(比如按钮)去除之后,该内存才可能得到回收。注意:内存地址十分的重要,一定要相同才可以删除
dispatchEvent
EventTarget 的 dispatchEvent() 方法会向一个指定的事件目标派发一个 Event,并以合适的顺序(同步地)调用所有受影响的 EventListener。标准事件处理规则(包括事件捕获和可选的冒泡过程)同样适用于通过手动使用 dispatchEvent() 方法派发的事件。
和经由浏览器触发,并通过事件循环异步调用事件处理程序的“原生”事件不同,dispatchEvent() 会同步调用事件处理函数。在 dispatchEvent() 返回之前,所有监听该事件的事件处理程序将在代码继续前执行并返回。
注意: 在调用此方法时,Event.target 属性默认为当前的 EventTarget。
使用代码来生成事件的步骤:首先用Event 构造函数创建一个新的 Event 对象。然后,使用 dispatchEvent() 方法触发事件。
Event 构造函数
文档地址:Event() 构造函数
语法: let event = new Event(type, [,options]);
返回值:无(undefined)
参数:
type :指定事件类型,比如click。
options 可选:为对象类型,有两个属性
bubbles:Boolean类型,表示事件是否冒泡。默认值 false,如果为true,则事件冒泡,反之亦然。
cancelable:Boolean类型,表示事件是否能取消。默认值 false,如果为true,则能取消,反之亦然。
composed:Boolean类型,默认值为 false,指示事件是否会在影子 DOM 根节点之外触发侦听器。
创建了一个点击事件: let clickEvent = new Event('click');
dispatchEvent 使用
创建完事件后,我们就可以使用dispatchEvent()。方法在目标元素上触发它: element.dispatchEvent(event);
<body> <script> window.onload=function(){ var myDiv=document.getElementById('myDiv') // 页面加载完成直接触发 myDiv.addEventListener('click', function () { alert('点击了'); }); let clickEvent = new Event('click'); myDiv.dispatchEvent(clickEvent); } </script> <div id="myDiv" style="width: 100px;height:100px;border:1px #ccc solid"></div> </body>
区分事件是由用户触发还是代码触发:event.isTrusted 属性为 true。如果事件由代码触发,则 event.isTrusted 为 false。
建议写法
Event 接口表示在 DOM 中出现的事件。有许多不同类型的事件,其中一些使用基于 Event 主接口的二次接口,点击查看Event 接口列表。例如 MouseEvent、TouchEvent、FocusEvent 和 KeyboardEvent。我们最好使用 例如 MouseEvent 这样的详细事件构造函数,而不是通用的 Event 构造函数,因为这些构造函数提供了更多特定于事件的信息。
当有很多嵌套的元素,并且每一个元素都有着自己的事件处理函数,事件处理过程会变得非常复杂。尤其当一个父元素和子元素绑定有相同类型的事件处理函数的时候。因为结构上的重叠,事件处理函数可能会依次被触发,触发的顺序取决于事件冒泡和事件捕获在每一个元素上的设置情况。
//指定事件发生时相对于视口的水平和垂直坐标 let clickEvent = new MouseEvent("click", { bubbles: true, cancelable: true, clientX: 150, clientY: 150 });
removeEventListener
EventTarget 的 removeEventListener() 方法可以删除使用 EventTarget.addEventListener() 方法添加的事件。IE9 以下用 detachEvent() 代替。
语法
- removeEventListener(type, listener);
- removeEventListener(type, listener, options);
- removeEventListener(type, listener, useCapture);
返回值:无(undefined)
参数
type:字符串,表示需要移除的事件类型。
listener:需要从目标事件移除的事件监听器函数。
options 可选:指定事件侦听器特征的可选对象。可选项有:
capture: 布尔值类型,默认值为 false。指定需要移除的事件监听器函数是否为捕获监听器。
passive 可选:布尔值,默认值为 false。设置为 true 时,表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。
useCapture 可选:布尔值,默认值为 false。指定需要移除的事件监听器函数是否为捕获监听器。true - 在捕获阶段移除事件句柄,false - 在冒泡阶段移除事件句柄。
注意: 如果添加两次事件,一次在捕获阶段,一次在冒泡阶段,你必须单独移除该事件。
移除时传入的参数与添加处理程序时使用的参数必须相同
<button id="myBtn">Event</button> <script> var btn = document.getElementById("myBtn"); btn.addEventListener("click",clickFn,false); function clickFn() { alert(this.id); // option.passive 不同不影响结果,option.capture 与 useCapture 不同影响是否成功 // btn.removeEventListener("click",clickFn ,{ passive: true, capture: true }, false);// 失败 // btn.removeEventListener("click",clickFn ,{ passive: true }, false);// 成功 // btn.removeEventListener("click",clickFn ,{ passive: true }) // 成功 // btn.removeEventListener("click",clickFn , true); // 失败 // btn.removeEventListener("click",clickFn , false); // 成功 } </script>
还有一种移除事件监听器的方法:可以向 addEventListener()
传入一个 AbortSignal
,稍后再调用拥有该事件的控制器上的 abort()
方法即可。
相关文章:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?