事件冒泡与事件捕获

最近面试被问到关于事件冒泡和捕获的知识,大部分都还记得,栽在了IE上面(IE8-只有冒泡没有捕获,IE9+支持捕获),回来记忆,顺便把一些和事件流有关的内容再梳理一遍。

我的理解:

事件冒泡

顾名思义,气泡从小变大,从冒泡起点到越来越大,所以是从目标事件源扩散出去的,一直到HTML根元素,期间遇到的同类型的事件也被自动触发;(IE和常用浏览器都支持)

事件捕获

从根元素开始,逐渐逐渐缩小范围,直到目标事件源,期间遇到的同类型事件也被自动触发;(除了IE的常用浏览器)

事件流

就是事件的流向,先捕获,再到事件源,最后再冒泡,一共分三个阶段:捕获阶段,目标阶段,冒泡阶段。(W3C标准,当处于目标阶段时事件触发)

事件委托/代理机制

利用冒泡机制来传递,那可以让某个父节点统一处理事件,通过判断事件的发生地(即事件产生的节点),然后做出相应的处理。就是将子元素的事件处理程序绑定到父类上,例如常见的ul>li> a列表标签的写法应用。这样可以减少绑定事件。

在一些标准的浏览器中,如Chrome、Firefox等,支持这两种冒泡方式。而事实上,准确的说,是这两种方式的混合方式。因为W3C采取的就是这两种方式的结合:先从顶级节点开始,将事件向下传递至源节点,再从源节点冒泡至顶节点。

而在IE及Opera(以下说的都是老版本的欧朋,新版本的欧朋经检测是支持事件捕获的)下,是不支持事件捕获的。而这个特点最明显体现在事件绑定函数上。

IE、Opera的事件绑定函数是attachEvent,而Chrome等浏览器则是addEventListener,而后者比前者的参数多了一个——这个参数是一个布尔值,这个布尔值由用户决定,用户若设为true,则该绑定事件以事件捕获的形式参与,若为false则以事件冒泡的形式参与,默认为false;

ele.addEventListener("click",function(e){
	e.stopPropagation();
})
// 这样ele的父元素就接收不到事件了

stopPropagation()方法既可以阻止事件冒泡,也可以阻止事件捕获,也可以阻止处于目标阶段

无论事件流中只有捕获还是事件流中只有冒泡,还是说是事件流中既有捕获还有冒泡,event.stopPropagation()都可以阻止事件流的传播顺序。

stopPropagation:防止对事件流中当前节点的后续节点中的所有事件侦听器进行处理。

只要是event.stopPropagation()加在哪里,则到哪里就停止运行,停止捕获或者停止冒泡,简单说是,仍然按照正常的混合机制流程走,只是哪里有e.stopPropagation()则这个流程到哪里就停止了,!!!但是只是阻止当前事件,如果后续还有绑定则会继续触发,也就是说,不是彻底取消click事件。

element.addEventListener('click', function (event) {
  event.stopPropagation();
  console.log(1);//不会触发
});

element.addEventListener('click', function(event) {
  // 会触发
  console.log(2);
});

stopImmediatePropagation: 简单说就是当前节点,同事件类型情况下,如果执行了该方法,则当前事件内执行,后续同类型事件不执行。与stopPropagation()有区别;

<!DOCTYPE html>
<html>
    <head>
        <style>
            p { height: 30px; width: 150px; background-color: #ccf; }
            div {height: 30px; width: 150px; background-color: #cfc; }
        </style>
    </head>
    <body>
        <div>
            <p>paragraph</p>
        </div>
        <script>
            const p = document.querySelector('p')
            p.addEventListener("click", (event) => {
              alert("我是p元素上被绑定的第一个监听函数");//执行
            }, false);

            p.addEventListener("click", (event) => {
              event.stopImmediatePropagation();
              alert("我是p元素上被绑定的第二个监听函数");//执行
              // 执行stopImmediatePropagation方法,阻止click事件冒泡,
              //并且阻止p元素上后续绑定的其他click事件的事件监听函数的执行.
            }, false);

            p.addEventListener("click",(event) => {
              alert("我是p元素上被绑定的第三个监听函数");
              // 该监听函数排在上个函数后面,该函数不会被执行
            }, false);

            document.querySelector("div").addEventListener("click", (event) => {
              alert("我是div元素,我是p元素的上层元素");
              // p元素的click事件没有向上冒泡,该函数不会被执行
            }, false);
        </script>
    </body>
</html>

可以使用DOM3级新增事件stopImmediatePropagation()方法来阻止事件捕获,那么 stopImmediatePropagation() 和 stopPropagation()的区别在哪儿呢?
后者只会阻止冒泡或者是捕获。 但是前者除此之外还会阻止该元素的其他事件发生,但是后者就不会阻止其他事件的发生(从而需要设置取消默认)。

阻止默认事件

有一些html元素默认的行为,比如说a标签,点击后有跳转动作;form表单中的submit类型的input有一个默认提交跳转事件;reset类型的input有重置表单行为。

 e.preventDefault();//非IE
 e.returnValue();//IE下阻止默认

阻止事件冒泡


let e = e||window.event;
if(e.stopPropagation){
  e.stopPropagation();//其它浏览器
}else{
  e.cancelBubble = true;//IE浏览器
}

绑定与解绑

/**
 * @Date: 2019-10-16 09:52:56
 * @param element:目标元素
 * @param eType:事件类型
 * @param handle:回调函数
 * @param bol:是否捕获
 * @author lg
 * @desc:事件绑定与解绑
 **/

function addEvent(element, eType, handle, bol) {
  if (element.addEventListener) {
    //如果支持addEventListener (主流浏览器和IE9+)
    element.addEventListener(eType, handle, bol);
  } else if (element.attachEvent) {
    //如果支持attachEvent (IE8-)
    element.attachEvent("on" + eType, handle);
  } else {
    //否则使用兼容的onclick绑定
    element["on" + eType] = handle;
    //element.onclick = function abc(){ alert('abc'); }
  }
}

function removeEvent(element, eType, handle, bol) {
  if (element.removeEventListener) {
    //如果支持removeEventListener (主流浏览器和IE9+)
    element.removeEventListener(eType, handle, bol);
  } else if (element.detachEvent) {
    //如果支持detachEvent(IE8-)
    element.detachEvent("on" + eType, handle);
  } else {
    //否则使用兼容的onclick绑定
    element["on" + eType] = null;
    //element.onclick = null;
  }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值