likes
comments
collection
share

addEventListener()第三个参数一定是useCapture吗?

作者站长头像
站长
· 阅读数 39

addEventListener()第三个参数一定是useCapture吗? 回答:不一定是useCapture,还可以是一个对象

那么这个对象可以是什么呢 ?读完文章相信我们就能回答上这个问题了。

概述

方法是将指定的监听器注册到EventTarget上,当该对象触发指定的事件时,指定的回调函数就会被执行。 事件目标可以是一个文档上的元素Element,Document和Window或者任何其他支持事件的对象(比如XMLHttpRequest)。 addEventListener()的工作原理是将实现EventListener的函数或对象添加到调用他的EventTarget上的指定事件类型的事件侦听器列表中。

语法

target.addEventListener(type, listener, options);
target.addEventListener(type, listener, useCapture);
target.addEventListener(type, listener, useCapture, wantUntrusted); / /Gecko/Mozilla only

参数

type 表示监听事件类型的字符串。 listener 当所监听的事件列星触发时,会接收到一个通知对象,listener必须是一个实现了EventListener接口的对象,或者是一个函数

btnDom.addEventListener('click', function(event) {
    alert('btn clicked 1');
});
btnDom.addEventListener('click', {
    handleEvent: function(event) {
        alert('btn clicked 2')
    }
});

option(可选) 一个指定有关listener属性的可选参数对象,可用的选项如下

参数值类型描述
captureBoolean该类型的事件捕获阶段传播到该EventTarget时触发
onceBoolean添加后最多只调用一次,如果为true。listener会在被调用之后自动移除
passiveBoolean设置为true时,标识listener永远不会调用preventDefault(),如果listener仍然调用了这个函数,客户端将会忽略并抛出一个控制台警告
signalAbortSignal该AbortSignal的abort() 方法被调用时,监听器会被移除
mozSystemGroupBoolean只在 XBL 或者Firefox chrom中使用,true表示listener被添加到system group中

useCapture Boolean,在dom树中,注册了listener元素,是否要犹豫他下面的EventTarget,调用该listener。当设置为true是,沿着dom树向上冒泡的事件,不会触发listener,当一个元素嵌套了另一个元素,并且两个元素对同一事件才注册了一个处理函数是,所发生的事件冒泡和事件捕获是两种不同的事件传播方式,事件传播模式决定了元素一那个顺序接受事件。事件流Event order

addEventListener()第三个参数一定是useCapture吗?

wantsUntrusted 如果为true,则时间处理程序会就会接受网页自定义的事件,此参数只适用于Gecko(chrome的默认值是true,其他常规网页的默认值是false),主要用于附加组件的代码和浏览器本身

用法说明

事件监听回调

事件监听器可以被指定为毁掉函数或实现EventListener的对象,其handleEvent()方法用做回调函数。 回调函数本身具有与handleEvent()方法相同的参数和返回值;也就是说,回调函数接受一个参数,一个基于Event的对象,描述已发生的事件,并且它不返回任何内容。

function eventHandler(event) {
    if(event.type === 'fullscreenchange') {
    }
    else {}
}

option支持的安全检测

在旧版本的DOM的规定中,addEventListener()的第三个参数是一个布尔值标识在捕获阶段调用事件处理程序。 随着时间的推移,很明显需要更多的选项,与其在方法之中添加更多的参数(传递可选值将会变得异常复杂),倒不如把第三个参数改为一个包含了各种属性的对象,这些属性的值用来被配置删除事件侦听器的过程。

因为旧版本的浏览器(以及一些相对不算古老的)仍然假定第三个参数是布尔值,我们需要编写一些代码来有效的处理这种情况。

例如下面

let passiveSupported = false;
try {
    let options = Object.definedProperty({}, 'passice', {
        get: function() {
            passiveSupported = true;
        }
    });
    window.addEventListener('test', null, options);
} catch(err) {}

示例中为passive属性创建了一个带有getter函数的options对象;getter设置为一个标识,passiveSupported被调用后会把其设为为true。这意味着如果浏览器检查options对象上的passive值时,passiveSupported将会被设置为true,否则会被保持false。然后我们调用addEventListener()去设置一个指定这些选项的事件处理器,这样如果浏览器将第三个参数认定为对象,这些选项值就会被检查。

btnDom.addEventListener(
    'click',
    handleMouseUp,
    passiveSupported ? { passive: true} : false
)

案例

addEventListener()第三个参数一定是useCapture吗?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>addEventListener</title>
    <style>
        .outer, .middle, .inner1, .inner2 {
            display:block;
            width:520px;
            padding:15px;
            margin:15px;
            text-decoration:none;
        }
        .outer{
            border:1px solid red;
            color:red;
        }
        .middle{
            border:1px solid green;
            color:green;
            width:460px;
        }
        .inner1, .inner2{
            border:1px solid purple;
            color:purple;
            width:400px;
        }
    </style>
</head>
<body>
    <div class="outer">
        outer, once & none-once
        <div class="middle" target="_blank">
            middle, capture & none-capture
            <a class="inner1" href="https://www.mozilla.org" target="_blank">
                inner1, passive & preventDefault(which is not allowed)
            </a>
            <a class="inner2" href="https://developer.mozilla.org/" target="_blank">
                inner2, none-passive & preventDefault(not open new page)
            </a>
        </div>
    </div>
    <script>
        let outer  = document.getElementsByClassName('outer')[0];
        let middle = document.getElementsByClassName('middle')[0];
        let inner1 = document.getElementsByClassName('inner1')[0];
        let inner2 = document.getElementsByClassName('inner2')[0];

        outer.addEventListener(
            'click',
            function onceHandler(event){ 
                console.log('outer, once');
            },
            { once : true}
        );
        outer.addEventListener(
            'click',
            function noneOnceHandler(event) {
                console.log('outer, none-once, default');
            },
            { once : false }
        );
        middle.addEventListener(
            'click',
            function captureHandler(event) {
                //event.stopImmediatePropagation();
                console.log('middle, capture');
            },
            { capture : true }
        );
        middle.addEventListener(
            'click',
            function noneCaptureHandler(event) {
                console.log('middle, none-capture, default');
            },
            { capture : false }
        );
        inner1.addEventListener(
            'click',
            function passiveHandler(event) {
                // Unable to preventDefault inside passive event listener invocation.
                //在调用passive事件监听器内部不能使用preventDefault
                event.preventDefault();
                console.log('inner1, passive, open new page');
            },
            { passive : true }
        );
        inner2.addEventListener(
            'click',
            function passiveHandler(event) {
                // Unable to preventDefault inside passive event listener invocation.
                //在调用passive事件监听器内部不能使用preventDefault
                event.preventDefault();
                console.log('inner1, passive, open new page');
            },
            { passive : false }
        );
    </script>
</body>
</html>
转载自:https://juejin.cn/post/7093135883708301348
评论
请登录