欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

理解DOM事件流和事件代理

最编程 2024-08-07 14:14:36
...

事件流描述的是从页面中接收事件的顺序。
事件冒泡
事件开始时由最具体的元素(文档中嵌套层次最深的节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
事件捕获:不太具体的节点更早接收事件,最具体的节点最后接收事件。事件捕获的用意是在时间到达预定目标之前捕获它。

当点击页面中的div时,
冒泡阶段:Element div --> Element body --> Element html --> Document
捕获阶段:Document --> Element html --> Element body -->Element div

DOM事件流
“DOM2级事件”规定的DOM事件流包括三个阶段:
事件捕获阶段 -- > 处于目标阶段 -- > 事件冒泡阶段。
在DOM事件流中,实际的目标在捕获阶段不会接收到事件。

DOM0级事件处理程序
传统方式,将一个函数赋值给一个事件处理程序属性。简单,且具有跨浏览器的属性。

btn.onclick = function(){
      alert(''Clicked);
}

DOM0级方法指定的事件处理程序被认为是元素的方法,因此,是在元素的作用域中执行,this引用当前元素。
这种方法添加的事件处理程序会在事件冒泡阶段被处理。
删除事件:btn.onclick = null

DOM2级事件处理程序
DOM2级事件定义两个方法:addEventListener() 和 removeEventListener()
所有的DOM节点中都包含这两个方法,并且都接收三个参数:时间名、事件处理函数、布尔值(true:捕获阶段调用事件处理程序 false:冒泡阶段调用事件处理程序)。
与DOM0级方法一样,这里添加的事件处理程序也是在其依附的元素的作用域中运行。
DOM2级方法的好处是:可以添加多个事件处理程序:

btn.addEventListener('click', function(){
  alert('click1');
}, false);
btn.addEventListener('click', function(){
  alert('click2');
}, false);

为按钮添加了两个点击事件的处理程序,按照添加顺序触发。
通过addEventListener添加的事件处理程序只能通过removeEventListener来移除,

var handler = btn.addEventListener('click', function(){
  alert('click1');
}, false);
btn.removeEventListener('click', handler, false);

第二个参数中传入的函数必须与addEventListener中的函数是同一个。

大多数情况下,都是将事件处理程序添加到冒泡阶段,这样可以最大限度的兼容各种浏览器。最好只在需要在事件到达目标前截获时才将事件处理程序添加到捕获阶段。

事件委托
在JS中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能。导致这一问题的原因是多方面的。首先,每个函数都是对象,会占用内存,内存占用越多,性能就越差;其次,必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。而事件委托,就是有效提升性能的一种解决方案。

对”事件处理程序过多“问题的解决方案就是事件委托,其利用了事件冒泡。例如,click事件会一直冒泡到document层次,那我们可以为整个页面指定一个onclick事件处理程序(需要时可以通过检测target的某些属性来采取适当的操作),而不必给每个可单击的元素分别添加事件处理程序。

如果可行的话,也可以考虑为document对象添加一个事件处理程序,用于处理页面上发生的某种特定类型的事件。这样相比传统做法有以下优点:

  • document对象很快就可以访问到,而且可以在页面生命周期的任何节点上为它添加事件处理程序(无需等待DOMContentLoaded或是load事件)。换句话说,只要可单击的元素呈现在页面上了,就可以立即具备相应的功能。
  • 在页面中设置处理程序所需的时间更少。只添加一个事件处理程序所需的DOM引用更少,所花时间也更少。
  • 整个页面占用的内存空间更少,能够提升整体性能。

最适合采用事件委托技术的时间包括click、mousedown、mouseup、keydown、keyup和keypress。虽然mouseover和mouseout事件也冒泡,但要适当处理经常需要计算元素位置(因为当鼠标从一个元素移到其子节点或者移出该元素时,都会触发mouseout)。