JS 基础篇(六):事件冒泡与捕获

您所在的位置:网站首页 事件捕获事件冒泡的应用场景 JS 基础篇(六):事件冒泡与捕获

JS 基础篇(六):事件冒泡与捕获

2023-10-14 02:07| 来源: 网络整理| 查看: 265

一、事件冒泡

微软提出了名为事件冒泡(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