前端面试题:JS的事件委托-事件的捕获与冒泡

说一下事件委托,或者对事件代理的理解。算是很常见的面试题了,应该说我遇见很多次了。刚开始遇见的时候发现自己不太懂,应该说之前自己用过,但是不知道他叫这个名字,后来也是总结面试题,去搜索了解了一下下,现在可以说是真正的搞懂了吧,今天把它分享出来,方便以后查看。

那什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计(红宝书)上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。要搞懂这个概念还得从事件冒泡开始,那什么是事件冒泡呢?

事件捕获(event capturing): 当鼠标点击或者触发dom事件时(被触发dom事件的这个元素被叫作事件源),浏览器会从根节点到事件源(由外到内)进行事件传播。

事件冒泡(dubbed bubbling):事件冒泡刚好相反,事件源到根节点(由内到外)进行事件传播。

无论是事件捕获还是事件冒泡,它们都有一个共同的行为,就是事件传播。dom标准事件流的触发的先后顺序为:先捕获再冒泡。即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。

element.addEventListener(event, function, useCapture);

在我们平常用的addEventListener方法中,一般只会用到两个参数,一个是需要绑定的事件,另一个是触发事件后要执行的函数,然而,addEventListener还可以传入第三个参数,第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。

举个例子:在页面中 DIV > Ul > Li ,那么添加下列事件:

var parent = document.getElementById("parent");
var brother = document.getElementById("brother");
var child = document.getElementById("child");
parent.addEventListener("click",function(e){
      console.log("1");
    },false
);
brother.addEventListener("click",function(e){
      console.log("2");
    },false
);
child.addEventListener("click",function(e){
      console.log("3");
    },false
);

当我们点击里边的LI的时候,那么触发的顺序为123,但是当我们把false改为true的时候,顺序就会反过来,这就是我们所说的事件的捕获和冒泡。

下面我们来说一下什么是事件委托。用别人那个通俗易懂的例子来说:

有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。

这里其实还有2层意思的:

1、现在委托前台的同事是可以代为签收的,即程序中的现有的dom节点是有事件的;

2、新员工也是可以被前台MM代为签收的,即程序中新添加的dom节点也是有事件的。

一般来说,dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了,那如果是很多的dom需要添加事件处理呢?比如我们有100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li。这样的话会出现很多的交互,使页面变慢,而且每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,而且我还只是说了一百个,成千上万个呢,只会更加糟糕。

所以这时候我们会用到事件委托,把相同的事件添加到父元素上,通过冒泡触发:( Ul > 5 * li

window.onload = function(){
   var oUl = document.getElementById("ul1");
   oUl.onclick = function(){
        alert(123);
    }
}

这个时候点击任何一个li都会触发弹出123,相对于给每一个li添加一个点击事件是不是就简单了很多呢。如果非要监听li的点击才触发弹出的话,也是可以解决的。只需要检测点击的元素标签名是不是li即可:

window.onload = function(){
  var oUl = document.getElementById("ul1");
  oUl.onclick = function(ev){
    var ev = ev || window.event;
    var target = ev.target || ev.srcElement;
    if(target.nodeName.toLowerCase() == 'li'){
        	alert(123);
         alert(target.innerHTML);
    }
  }
}

 

你可能感兴趣的:(三大基础,面试题库,个人总结,dom,javascript)