js从事件流到事件委托及target与currentTarget

事件流

事件流一般分为三个部分,以下解析均在DOM level 2事件下,DOM leve 0不支持捕获


先来解释一下addEventListener() 这个方法

当我们使用addEventListener添加事件时,该方法有四个参数,分别为:

  1. 事件类型
  2. listener callback
  3. options 可选
    一个指定有关 listener 属性的可选参数对象。可用的选项如下:
    capture: Boolean,表示 listener 会在该类型的事件捕获阶段传播到该 EventTarget 时触发。
    once: Boolean,表示 listener 在添加之后最多只调用一次。如果是 true, listener 会在其被调用之后自动移除。
    passive: Boolean,表示 listener 永远不会调用 preventDefault()。如果 listener 仍然调用了这个函数,客户端将会忽略它并抛出一个控制台警告。
    mozSystemGroup: 只能在 XBL 或者是 Firefox’ chrome 使用,这是个 Boolean,表示 listener 被添加到 system group。
  4. boolean 可选
    该参数就是我们此次关注的重点;

整个事件流过程

js从事件流到事件委托及target与currentTarget_第1张图片

  • 捕获阶段
    当我们在addEventListener 的参数中添加了true ,如下:

    // $0是父节点
    $0.addEventListener('click', (e) => {console.log('捕获click')}, true);
    

    此时这个事件会在捕获过程被响应

  • 目标阶段

    该阶段即相应目标节点事件

  • 冒泡阶段

    // 该参数默认是false;
    // $0是父节点;
    // 可以在这里使用 stopPropeagation()阻止继续冒泡,也可以使用preventDefault()阻止默认事件;
    // 也可以直接 return false; 冒泡和默认事件都会被阻止;
    $0.addEventListener('click', (e) => {console.log('冒泡click')});
    
    

改变捕获和冒泡的顺序

这是一个面试题,主要想考核的其实是你对于js异步的了解和掌握,下一篇会写一个关于事件循环的,把这个弄懂了,这种问题就很好解决了

document.body.addEventListener('click', (e) => {
    setTimeout(() => {
        console.log('异步 event catch 事件捕获');
    }, 0)
}, true)
document.body.addEventListener('click', (e) => {
    console.log('event bubble 事件冒泡');
})

结果如下:
js从事件流到事件委托及target与currentTarget_第2张图片

未异步结果如下:
js从事件流到事件委托及target与currentTarget_第3张图片


应用场景

虽然事件流有这三个过程,但是我们应用场景最多的还是利用冒泡来实现的时间代理或者叫事件委托;即父节点定义事件,通过e.target来找到目标节点实现相应的效果;最常见的就是ul上定义事件,代理后面所有的li;
那如果我们只想获取定义事件的节点信息怎么办呢,除了e.target 还有个e.currentTarget ,此属性指向的就是定义了事件的节点。但是当我们打印出来的话可能会出现如下这中情况:
js从事件流到事件委托及target与currentTarget_第4张图片
但是当我们直接打印它的话,我们会发现其实是有值的,在Stack Overflow里找到了很形象的解释:

var foo = { };
for (var i = 0; i < 100; i++) {
    foo['longprefix' + i] = i;
}
console.log(foo);
foo.longprefix90 = 'abc';

上面这个例子中,虽然在调用console.log(foo)的时候foo.longprefix90应该是90,但是当你在console里浏览object的时候你会看到foo.longprefix90abc
这是JavaScript consolelog一个对象的机制造成的。log 没有包含对象的所有属性,它只包含了对这个对象的引用。当你点击展开时,他才会给你找那个对象的属性。
所以,之所以为null的情况是,当调用console.log(e)时,currentTarget属性是有值的,但是过后这个值就被重置为null了。所以当你展开事件对象,看到的就是null

你可能感兴趣的:(js)