JavaScript 事件处理模型:冒泡&捕获

JS事件处理模型

01 前言

  1. 事件冒泡:结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素(自底向上
  2. 事件捕获:结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)(自顶向下
  3. 一个对象的一个事件类型绑定一个处理函数只能遵循一个事件模型,但是若一个对象的一个事件类型绑定两个处理函数,那么触发顺序:先捕获,后冒泡
  4. element.addEventListener(event-type, function, false/true)方法用于向指定元素添加事件句柄,IE8 及更早IE版本不支持该方法。
参数 描述
event-type 必须 字符串,指定事件名。注意: 不要使用 “on” 前缀。
function 必须 指定要事件触发时执行的函数。当事件对象会作为第一个参数传入函数。
false/true 可选 布尔值,指定事件是否在捕获或冒泡阶段执行。(false-默认:事件句柄在冒泡阶段执行;true :事件句柄在捕获阶段执行)

02 事件冒泡

  • 同一事件,自子元素冒泡向父元素,即 自底向上 。
  • 标准的方法:元素.addEventListener(event-type,function,false)
  • 注:focus, blur, change, submit, reset,select 等事件不冒泡。

2.1 实例

冒泡(结构自底向上

  • html代码如下:
<div class="wrapper">
    <div class="content">
        <div class="box"></div>
    </div>
</div>
  • css代码如下:
.wrapper {
    
    
    width: 300px;
    height: 300px;
    background-color: red;
}

.content {
    
    
    width: 200px;
    height: 200px;
    background-color: green;
}

.box {
    
    
    width: 100px;
    height: 100px;
    background-color: yellow;
}
  • JavaScript代码如下:
wrapper.addEventListener('click', function () {
    
    
    console.log('wrapper');
}, false); // wrapper
content.addEventListener('click', function () {
    
    
    console.log('content');
}, false); // content  wrapper
box.addEventListener('click', function () {
    
    
    console.log('box');
}, false); // box  content  wrapper
  • 代码运行效果如下:
    maopao.gif
    maopao

2.2 取消冒泡

  • W3C标准 event.stopPropagation();(不支持IE9以下版本)
  • IE独有 event.cancelBubble = true;(谷歌其实也实现了)
div.onclick = function (e) {
    
    
    // e 事件对象
    e.stopPropagation(); //事件对象提供了一个可以取消冒泡的方法
    // e.cancelBubble = true; 这个也可
};

注:在每一个事件处理函数里面可以写一个形参,如上面代码中的形参e(一个就可以了,多了没用)。虽然我们不能传递数据,但是系统会自动帮我们传一个事件对象,这个事件对象有很多属性,每一个属性记载了这个事件发生时的一些关键性数据和信息,如事件类型,事件时刻,鼠标的一些坐标点等等。系统会将其打包来供我们使用(注:IE里面会失效,但是IE里面有window.event来记录)

  • 封装取消冒泡的函数stopBubble(event)
function stopBubble(event) {
    
    
    if (event.stopPropagation) {
    
    
        event.stopPropagation();
    } else {
    
    
        e.cancelBubble = true;
    }
}

03 事件捕获

  • 同一事件,自父元素捕获至子元素,即 自顶向下 。
  • 标准的方法:元素.addEventListener(event-type,function,true)

3.1 实例

捕获 (结构自顶向下

  • html代码如下:
<div class="wrapper">
    <div class="content">
        <div class="box"></div>
    </div>
</div>
  • css代码如下:
.wrapper {
    
    
    width: 300px;
    height: 300px;
    background-color: red;
}

.content {
    
    
    width: 200px;
    height: 200px;
    background-color: green;
}

.box {
    
    
    width: 100px;
    height: 100px;
    background-color: yellow;
}
  • JavaScript代码如下:
wrapper.addEventListener('click', function () {
    
    
    console.log('wrapper');
}, true); // wrapper
content.addEventListener('click', function () {
    
    
    console.log('content');
}, true); // wrapper  content 
box.addEventListener('click', function () {
    
    
    console.log('box');
}, true); // wrapper  content  box
  • 代码运行效果如下:
    buhuo.gif
    buhuo

04 阻止默认事件

  • 默认事件:浏览器通过HTML标签或DOM元素提供的一些功能性的默认行为,包括表单提交a标签跳转右键呼出菜单(contextmenu是右键出菜单事件)等。

  • 所以我们可以通过js取消或更改这些默认事件:
    (1) return false; (以对象属性的方式注册的事件才生效,虽然兼容性非常好,但只有句柄方式(‘on’)绑定的事件才能好用 。)
    (2) event.preventDefault(); (W3C标准,IE9以下不兼容)
    (3) event.returnValue = false; (兼容IE)

  • 封装阻止默认事件的函数cancelHandler(event);

// 封装函数cancelHandler
function cancelHandler(event) {
    
    
    if (event.preventDefault) {
    
    
        event.preventDefault();
    } else {
    
    
        event.returnValue = false;
    }
}

// 测试实例如下:

// 方式一:调用函数---阻止右键呼出菜单事件
document.oncontextmenu = function (e) {
    
    
    console.log('a');
    cancelHandler(e);
}

// 方式二:对句柄方式绑定的事件采用return false;
var a = document.createElement('a');
a.innerHTML = 'www.baidu.com';
a.href = '#';
document.body.appendChild(a);
//阻止a标签跳转事件
a.onclick = function () {
    
     
    return false;
}

个人笔记,欢迎大家交流探讨!

猜你喜欢

转载自blog.csdn.net/Yuki_yuhan/article/details/108558215