JS事件处理模型
01 前言
- 事件冒泡:结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素(自底向上)
- 事件捕获:结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)(自顶向下)
- 一个对象的一个事件类型绑定一个处理函数只能遵循一个事件模型,但是若一个对象的一个事件类型绑定两个处理函数,那么触发顺序:先捕获,后冒泡。
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
- 代码运行效果如下:
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
- 代码运行效果如下:
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;
}
个人笔记,欢迎大家交流探讨!