从onClick谈事件代理和了解事件传播机制

javasriptdelegate这个词经常出现,看字面的意思,代理、委托。

要搞懂事件代理,我们先来看看什么是代理,相信我们生活中现在还有朋友在做微商的,而微商的产品就是一级一级代理,下家找上家拿货这样子,你卖了东西从上家拿货,这个过程相当于你也有了货

我们怎么从字面上来了解事件的代理呢?慢慢来,我们先来看一个需求,有这样一个列表,当我们每次点击的时候,就在控制台打印列表里的内容

作为一名新手,我经常这样绑定onclick事件

我会循环每一个li当我点击一个在控制台显示打印结果,全部绑定click事件,于是,我的代码是这样的

 
  • 我是一号
  • 我是二号
  • 我是三号
  • 我是四号
  • 我是五号
var ul = document.querySelector(".ct") for(var i=0;i
从onClick谈事件代理和了解事件传播机制_第1张图片
代码没有问题

我觉得这样写的挺好的,可是有人说这样会耗费性能,那我就不管了,可是当我改了一下需求,我发现这个代码用的没那么舒服了

我在代码中通过js加入新的li,当我点击新的li时,控制台没有打印我的代码?怎么回事?

我加入了几这样的代码

var btn =document.querySelector("#btn")
var i =6
btn.addEventListener("click",function(){
  var node = document.createElement("li")
  node.innerText = "我是" + i++ + "号"
  ul.appendChild(node)
})
从onClick谈事件代理和了解事件传播机制_第2张图片
后面增加的li没有在控制台打印

这是为什么?因为原有的li跟我后面生成的li根本不是同时发生的,在创建新的li元素之前,已经给存在的li加事件了,好吧,那我怎么修改呢?难道要重新循环遍历,太麻烦了,

有人告诉我可以用代理,代理是什么,看了文章,好吧,修改一下代码

ul.addEventListener("click",function(e){
 // 检查事件源e.targe是否为Li
  if(e.target.nodeName.toLowerCase() == 'li'){
    console.log(e.target.innerText)
  }
})

从onClick谈事件代理和了解事件传播机制_第3张图片
成功了

新增新的点击 li也会再控制台打印,解决了,于是耐心翻资料看了一下什么是事件代理:

定义:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

那什么是冒泡呢?

  • 当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡

回到我们本文的这个例子,看看改动后的代码,我把onlick事件绑定到了ul标签上面,而不是li标签。于是,当我点击任何一个li标签(不管是动态生成的还是之前就有的)是,这个事件就开始冒泡,寻找父元素。由于我这里给ul绑定了onlick,那么这时,ul会捕获冒泡上来的onclick事件。

接着,如果,这个target刚刚好就是li标if(target.nodeName.toLowerCase() == 'li'),那么执行函数。

简单介绍一下事件传播机制,主要介绍DOM2.0

  • DOM2.0模型将事件处理流程分为三个阶段:一、事件捕获阶段,二、事件目标阶段,三、事件起泡阶段。如图:
从onClick谈事件代理和了解事件传播机制_第4张图片
事件传播
  • 事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。

  • 事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。

  • 事件起泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)来组织事件的冒泡传播。

你可能感兴趣的:(从onClick谈事件代理和了解事件传播机制)