文章目录
前言
大家有没有思考过一个问题——html中的标签都是相互嵌套的,document是最外面的大盒子。当你单击一个div时,同时你也单击了div的父元素,甚至整个页面。那div的单击事件如何执行?这就涉及到 JS中 DOM事件流 的相关知识点了,请看下文!
一、DOM事件流
1.什么是事件流呢?
事件流:描述的是从页面中接收事件的顺序,事件发生时在元素节点按照一定的顺序执行就叫做DOM事件流。
2.事件流的两种方式
2.1 事件冒泡
所谓的冒泡就是事件的逐级向上传导的过程,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发。
2.1.1 事件冒泡方式
示例图:
如下图所示,因为子元素以及父元素在设置监听事件时均设置的是在事件的冒泡阶段调用回调函数,单击子元素时,因为事件的冒泡此单击事件会一直冒泡到父元素中。
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="father">father盒子
<div class="son">son盒子</div>
</div>
<script>
// onclick 和 attachEvent(ie) 在冒泡阶段触发
/*
冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略
如果参数为true,则为捕获阶段
*/
// son -> father ->body -> html -> document
var son = document.querySelector('.son');
// 给son注册单击事件
son.addEventListener('click', function (event) {
alert('son');
// // 阻止事件冒泡
// event.stopPropagation();
}, false);
// 给father注册单击事件
var father = document.querySelector('.father');
father.addEventListener('click', function (event) {
alert('father');
// // 阻止事件冒泡
// event.cancelBubble = true;
}, false);
// 给document注册单击事件,省略第3个参数
document.addEventListener('click', function () {
alert('document');
})
</script>
</body>
</html>
2.2 事件捕获
网景公司提出从最外层开始,然后一层一层接收事件并响应,也就是捕获事件流。
最终由w3c统一了最后标准,先捕获在冒泡,现代的浏览器都遵循此标准。
示例图:
如下图所示,若给 father 盒子设置在监听点击事件时,在事件的捕获阶段调用函数,按照事件捕获的执行顺序,当点击该项时会先执行该项,接着向内执行子元素(son盒子),最后执行 document 语句
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="father">father盒子
<div class="son">son盒子</div>
</div>
<script>
// onclick 和 attachEvent(ie) 在冒泡阶段触发
/*
冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略
如果参数为true,则为捕获阶段
*/
// son -> father ->body -> html -> document
var son = document.querySelector('.son');
// 给son注册单击事件
son.addEventListener('click', function (event) {
alert('son');
// // 阻止事件冒泡
// event.stopPropagation();
}, false);
// 给father注册单击事件
var father = document.querySelector('.father');
father.addEventListener('click', function (event) {
alert('father');
// // 阻止事件冒泡
// event.cancelBubble = true;
// 为该项设置在事件捕获阶段时,执行回调函数
}, true);
// 给document注册单击事件,省略第3个参数
document.addEventListener('click', function () {
alert('document');
},false)
</script>
</body>
</html>
2.3 DOM事件的3个阶段
1:捕获阶段
2:当前目标阶段
3:冒泡阶段
执行顺序——
document -> html->body->div(当前阶段) 事件捕获过程
(当前阶段) div->body->html->document 事件冒泡过程
小结
js 代码只能执行捕获或者冒泡的一个阶段
- onclick 和attachEevent 只能得到冒泡阶段
- addEventListener 第三个参数为true表示事件捕获阶段调用程序,如果false表示冒泡阶段调用处理程序
- 实际开发中一般使用冒泡。
- 没有冒泡的事件:onblur,onfocus,onmouseenter,onmouseleave。
二、事件对象
1.什么是事件对象
事件发生后把事件相关的一系列信息数据都放到对象里面,这就是事件对象。
2.事件对象的使用
- 标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
- 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="father">父元素
<div class="son">子元素</div>
</div>
<script>
var div = document.querySelector('div');
div.onclick = function (e) {
// 事件对象
e = e || window.event;
console.log(e);
}
</script>
</body>
</html>
运行结果:
3. e.target 和 this 的区别
- 常情况下terget 和 this是一致的,
- 但有一种情况不同,那就是在事件冒泡时(父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行),这时候this指向的是父元素,因为它是绑定事件的元素对象,而target指向的是子元素,因为他是触发事件的那个具体元素对象。
4.阻止事件的默认行为
- 阻止事件的默认行为—— e.preventDefault();
- 案例解析——常规情况下点击该链接时会自动跳转至百度页面这是事件的默认行为,若不想要这个效果,即可使用阻止事件的默认行为即可实现。
<a href="http://www.baidu.com">123</a>
<script>
var div = document.querySelector('a');
div.onclick = function(e) {
// 事件对象
e.preventDefault();
}
</script>
5.阻止冒泡
- 阻止冒泡的方式—— e.stopPropagation(); // stop 停止 Propagation 传播
window.event.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
案例解析——因为事件的冒泡,常规情况下当点击子元素时,该元素的事件也会向上冒泡到父元素身上,若向阻止这种行为,设置阻止冒泡即可。
<div class="father">父元素
<div class="son">son儿子</div>
</div>
<script>
var son = document.querySelector('.son');
// 给son注册单击事件
son.addEventListener('click', function (e) {
alert('son');
e.stopPropagation(); // stop 停止 Propagation 传播
window.event.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
}, false);
var father = document.querySelector('.father');
// 给father注册单击事件
father.addEventListener('click', function () {
alert('father');
}, false);
// 给document注册单击事件
document.addEventListener('click', function () {
alert('document');
})
</script>
总结
以上就是今天所要和大家分享的内容,就到此停笔吧~
其他的巴拉巴拉:今日依旧是个好天气,早起听到一首极其温柔的歌就觉得周围的事物都温柔了下来,其实相较于昨日也无甚特别的,大概是心境的变化吧,这大抵也是音乐的魅力所在吧……对了,最后依旧诚挚祝福屏幕前的你健康幸福、平安喜乐~