loading

在冒泡事件中绑定冒泡事件

先看代码

<div id="container">
  <div id="div"></div>
</div>
<script>
  const div = document.getElementById('div');
  const con = document.getElementById('container');

  div.addEventListener('click', function (e) {
    console.log('child click' + 111111);
    con.addEventListener('click', function () {
      console.log('father click' + 222222);
    })
  })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

父元素没有绑定事件,子元素绑定了点击事件,并同时给父元素绑定了一个点击事件,可以看一看,点击子元素之后输出的结果是怎么样的。

  • 结果:新绑定的father click也被触发了。

这里可以得出,事件冒泡的传递事件,是在绑定的handler触发之后的,但是最大多数情况下,我们肯定是不想让父元素新绑定的 click 触发的,不然图啥呢,直接初始化绑定就好了,也不用写在子元素的 handler 中。 那怎么解决呢,加个setTimeout(0)去给父元素添加事件,确实可以解决了这个问题。但是会让代码的可读性降了一个档次。

# 解决办法

事件触发时,有一个 timeStamp, createInvoker记录了元素绑定的时间,在接受到事件的时候,通过 timeStamp 和 attached 的比较,来决定是否运行这个事件绑定的 handler

Object.prototype.createEventListener = function (...args) {
  // handler
  const func = args[1];
  
  const invoker = function (...arguments) {
    const event = arguments[0];
    // 比较event触发的时间,和事件绑定的时间,如果event触发时候,事件还未绑定,则不运行
    if (event.timeStamp >= invoker.attached) {
      func(...arguments)
    }
  }
  // handler被绑定上的时间
  invoker.attached = performance.now();
  
  // 替换原来的handler
  args[1] = invoker;

  return this.addEventListener(...args);
}

div.createEventListener('click', function (e) {
  console.log('child click' + 111111);
  con.createEventListener('click', function () {
    console.log('father click' + 222222);
  })
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

点击第一次只有 child 打印,第二次点击,child 和 father 一起打印。

最近更新时间: 2021/08/25 17:25:09
最近更新
01
2023/07/03 00:00:00
02
2023/04/22 00:00:00
03
2023/02/16 00:00:00