0
点赞
收藏
分享

微信扫一扫

对事件委托的理解

1)事件委托的概念

事件委托本质上是利用了浏览器事件冒泡的机制。因为事件在冒泡过程中会上传到父节点,父节点可以通过事件对象获取到目标节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件委托(事件代理)。

使用事件委托可以不必要为每一个子元素都绑定一个监听事件,这样减少了内存上的消耗。并且使用事件代理还可以实现事件的动态绑定,比如说新增了一个子节点,并不需要单独地为它添加一个监听事件,它绑定的事件会交给父元素中的监听函数来处理。

2)事件委托的特点

  • 减少内存消耗

如果有一个列表,列表之中有大量的列表项,需要在点击列表项的时候响应一个事件:

<ul id="list">

  <li>item 1</li>

  <li>item 2</li>

  <li>item 3</li>

  ......

  <li>item n</li>

</ul>

如果给每个列表项一一都绑定一个函数,那对于内存消耗是非常大的,效率上需要消耗很多性能。因此,比较好的方法就是把这个点击事件绑定到他的父层,也就是 ul 上,然后在执行事件时再去匹配判断目标元素,所以事件委托可以减少大量的内存消耗,节约效率。

  • 动态绑定事件

给上述的例子中每个列表项都绑定事件,在很多时候,需要通过 AJAX 或者用户操作动态的增加或者去除列表项元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件;如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的,所以使用事件在动态绑定事件的情况下是可以减少很多重复工作的。

// 来实现把 #list 下的 li 元素的事件代理委托到它的父层元素也就是 #list 上:

// 给父层元素绑定事件

document.getElementById('list').addEventListener('click', function (e) {

  // 兼容性处理

  var event = e || window.event;

  var target = event.target || event.srcElement;

  // 判断是否匹配目标元素

  if (target.nodeName.toLocaleLowerCase === 'li') {

    console.log('the content is: ', target.innerHTML);

  }

});

在上述代码中, target 元素则是在 #list 元素之下具体被点击的元素,然后通过判断 target 的一些属性(比如:nodeName,id 等等)可以更精确地匹配到某一类 #list li 元素之上;

3)局限性

当然,事件委托也是有局限的。比如 focus、blur 之类的事件没有事件冒泡机制,所以无法实现事件委托;mousemove、mouseout 这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,因此也是不适合于事件委托的。

当然事件委托不是只有优点,它也是有缺点的,事件委托会影响页面性能,主要影响因素有:

  • 元素中,绑定事件委托的次数;
  • 点击的最底层元素,到绑定事件元素之间的DOM层数;

在必须使用事件委托的地方,可以进行如下的处理:

  • 只在必须的地方,使用事件委托,比如:ajax的局部刷新区域
  • 尽量的减少绑定的层级,不在body元素上,进行绑定
  • 减少绑定的次数,如果可以,那么把多个事件的绑定,合并到一次事件委托中去,由这个事件委托的回调,来进行分发。
举报

相关推荐

0 条评论