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() 方法即可。

相关文章:

MDN 介绍

addEventListener 用法

dispatchEvent() 代码触发事件

addEventListener()与removeEventListener(),追加事件和删除追加事件

posted @   柔和的天空  阅读(1250)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示