JS 基础篇(六):事件冒泡与捕获 |
您所在的位置:网站首页 › 事件捕获事件冒泡的应用场景 › JS 基础篇(六):事件冒泡与捕获 |
一、事件冒泡
微软提出了名为事件冒泡(event bubbling)的事件流。事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。 Click me! 在事件冒泡的概念下在p元素上发生click事件的顺序应该是p -> div -> body -> html -> document。 即如果p元素上绑定了click的处理事件将先被触发否则将冒泡到div,在div上如果绑定了click的处理事件将被触发否则将冒泡到body,以此类推,判断是否有click事件的处理函数,有就触发,没有就冒泡到上一级直到到达document级。 示例: s1 s2 s1.addEventListener("click",function(e){ console.log("s1 冒泡事件"); },false); s2.addEventListener("click",function(e){ console.log("s2 冒泡事件"); },false); //点击s2: //s2 冒泡事件 //s1 冒泡事件 //点击s1: //s1 冒泡事件 二、事件捕获网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。 Click me! 在事件捕获的概念下在p元素上发生click事件的顺序应该是document -> html -> body -> div -> p 即如果document元素上绑定了click的处理事件将先被触发否则将进入到html中,在html上如果绑定了click的处理事件将被触发否则将进入到body中,以此类推,判断是否有click事件的处理函数,有就触发,没有就进入到下一级直到到达到触发元素那一级。 示例: s1 s2 s1.addEventListener("click",function(e){ console.log("s1 捕获事件"); },true); s2.addEventListener("click",function(e){ console.log("s2 捕获事件"); },true); //点击s2: //s1 捕获事件 //s2 捕获事件 //点击s1: //s1 捕获事件 三、addEventListener的第三个参数在上面的案例中,我们对addEventListener的第三个参数进行了设置,下面将介绍下addEventListener函数第三个参数的含义。addEventListener的第三个参数就是为冒泡和捕获准备的. addEventListener有三个参数: element.addEventListener(event, function, useCapture) 第一个参数是需要绑定的事件 第二个参数是触发事件后要执行的函数 第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。 四、事件冒泡与事件捕获同时存在当事件捕获和事件冒泡一起存在的情况,事件又是如何触发呢。 这里记被点击的DOM节点为target节点: 1、document 往 target节点,捕获前进,遇到注册的捕获事件立即触发执行 2、到达target节点,触发事件(对于target节点上,是先捕获还是先冒泡则捕获事件和冒泡事件的注册顺序,先注册先执行) 3、target节点 往 document 方向,冒泡前进,遇到注册的冒泡事件立即触发 示例: //对于非target节点则先执行捕获在执行冒泡 //对于target节点则是先执行先注册的事件,无论冒泡还是捕获 s1 s2 s1.addEventListener("click",function(e){ console.log("s1 冒泡事件"); },false); s2.addEventListener("click",function(e){ console.log("s2 冒泡事件"); },false); s1.addEventListener("click",function(e){ console.log("s1 捕获事件"); },true); s2.addEventListener("click",function(e){ console.log("s2 捕获事件"); },true);点击s2,执行结果如下: s1 捕获事件 s2 冒泡事件 s2 捕获事件 s1 冒泡事件 分析: 点击s2,click事件从document->html->body->s1->s2(捕获前进) 这里在s1上发现了捕获注册事件,则输出"s1 捕获事件" 到达s2,已经到达目的节点, s2上注册了冒泡和捕获事件,先注册的冒泡后注册的捕获,则先执行冒泡,输出"s2 冒泡事件" 再在s2上执行后注册的事件,即捕获事件,输出"s2 捕获事件" 下面进入冒泡阶段,按照s2->s1->body->html->documen(冒泡前进) 在s1上发现了冒泡事件,则输出"s1 冒泡事件" 五、如何阻止事件冒泡或者事件捕获以冒泡事件为例: 1、通过event.stopPropagation()终止事件传播对某一个节点而言,如果不想它现在处理的事件继续往上冒泡的话,我们可以终止冒泡,即在相应的处理函数内,加入event.stopPropagation(),终止事件的广播分发,这样事件停留在本节点,不会再往外传播了。 s1 s2 s1.addEventListener("click",function(e){ console.log("s1 冒泡事件"); },false); s2.addEventListener("click",function(e){ e.stopPropagation(); //阻止冒泡到上面元素,冒泡链在此处中断 console.log("s2 冒泡事件"); },false); //原先点击s2: //s2 冒泡事件 //s1 冒泡事件 //阻止冒泡后点击s2: //s2 冒泡事件 2、对触发事件元素进行过滤事件包含最初触发事件的节点引用 和 绑定处理事件节点的引用,那如果节点只处理自己触发的事件即可,不是自己产生的事件不处理。 event.target指向的是触发事件的dom节点,而event.currrentTarget 指向的是绑定事件的dom节点,我们可以通过这两个target 是否相等,让绑定事件的dom节点只处理其自身触发的事件而不是下级冒泡传递上来的。 s1.addEventListener("click",function(event){ if(event.target === event.currentTarget){ console.log("s1 冒泡事件"); } },false); s2.addEventListener("click",function(event){ if(event.target === event.currentTarget){ console.log("s2 冒泡事件"); } },false);我们还可以获取target的节点名、id等属性进行过滤设置处理事件。 red yellow blue green black white var color_list = document.getElementById('color-list'); color_list.addEventListener('click',showColor,false); function showColor(e){ var x = e.target; if(x.nodeName.toLowerCase() === 'li'){ console.log('The color is ' + x.innerHTML); } }元素收到事件后,判断事件是否符合要求,然后做相应的处理,然后事件继续冒泡往上传递; 通过以上方式,我们把本来每个元素都要有的处理函数,都交给了其祖父节点元素来完成了,也就是说,li将自己的响应逻辑委托给ul,让它来完成相应逻辑,自己不实现相应逻辑,这个模式,就是所谓的事件委托。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |