前端小白的学习之路(事件流)
提示:事件捕获,事件冒泡,事件委托
目录
事件模型(DOM事件流)
1.事件是什么
2.事件流
1).事件流的三个阶段
3.参考代码
二、事件委托
1.概念
2.使用案例
3.阻止冒泡行为
事件模型(DOM事件流)
1.事件是什么
1). 事件是HTML和Javascript交互的驱动器, 事件是文档或者浏览器窗口中发生的,特定的交互瞬间。
2), 事件是用户或浏览器自身执行的某种动作,如 click,load 和 mouseover 都是事件的名字。
3). 事件是 javaScript 和 DOM 之间交互的桥梁。
2.事件流
事件流, 即是一个事件发生的流程或者说流转, 从开始到结束, 都发生了什么
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程,我们就称之为DOM事件流.
1).事件流的三个阶段
1. 捕获阶段 Capture Phase; 从上到下, 层层传递, 直到目标接收
2. 目标阶段 Target Phase; 确认目标, 进行处理
3. 冒泡阶段 Bubbling Phase; 处理结束, 往上传递.
注意:
1. JS建议执行捕获或者冒泡两个阶段中的其中一个阶段
2. 传统绑定事件方式跟attachEvent绑定事件的方式只能得到冒泡阶段
3. addEventListener(type,listener,[,useCapture])第三个参数如果是true,表示在事件捕获阶段调用事件处理程序; 如果是false(默认不写就是false),表示事件冒泡阶段调用事件处理程序.
4. 实际开发中我们很少使用事件捕获,我们更关注事件冒泡.
5. 另外需要注意, 不是所有事件都会冒泡的, 有些事件是没有冒泡的,比如onmouseenter,onmouseleave
6. 事件冒泡有时候会带来麻烦,有时候又会帮助我们很巧妙的做某些事件,我们会学习事件委托,事件委托(事件代理)的原理就是事件冒泡
7.监听绑定方式addEventListener()方法中第三个参数可以控制是在冒泡阶段触发还是在捕获阶段触发
3.参考代码
<!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>
<style>
* {
margin: 0;
padding: 0;
}
#father {
width: 400px;
height: 400px;
background: orange;
margin: 50px auto;
padding: 20px;
border: 10px solid red;
}
#father #son {
width: 150px;
height: 150px;
background: skyblue;
}
</style>
</head>
<body>
<div id="father">
<div id="son">son元素</div>
</div>
<script>
var son = document.getElementById("son");
var father = document.getElementById("father");
// son.onclick = function () {
// console.log("son元素的click事件");
// }
// father.onclick = function () {
// console.log("father元素的click事件");
// }
// document.body.onclick = function () {
// console.log("body元素的click事件");
// }
// document.documentElement.onclick = function () {
// console.log("html元素的click事件");
// }
// document.onclick = function () {
// console.log("document元素的click事件");
// }
// window.onclick = function () {
// console.log("window元素的click事件");
// }
/* son.attachEvent("onclick", function () {
console.log("son元素的click事件");
});
father.attachEvent("onclick", function () {
console.log("father元素的click事件");
});
document.body.attachEvent("onclick", function () {
console.log("body元素的click事件");
})
document.documentElement.attachEvent("onclick", function () {
console.log("html元素的click事件");
});
document.attachEvent("onclick", function () {
console.log("document元素的click事件");
});
window.attachEvent("onclick", function () {
console.log("window元素的click事件");
}); */
son.addEventListener("click", function () {
console.log("son元素的click事件");
},);
father.addEventListener("click", function () {
console.log("father元素的click事件");
});
document.body.addEventListener("click", function () {
console.log("body元素的click事件");
})
document.documentElement.addEventListener("click", function () {
console.log("html元素的click事件");
});
document.addEventListener("click", function () {
console.log("document元素的click事件");
});
window.addEventListener("click", function () {
console.log("window元素的click事件");
});
/* son.addEventListener("click", function () {
console.log("son元素的click事件");
}, false);
father.addEventListener("click", function () {
console.log("father元素的click事件");
}, false);
document.body.addEventListener("click", function () {
console.log("body元素的click事件");
}, false);
document.documentElement.addEventListener("click", function () {
console.log("html元素的click事件");
}, false);
document.addEventListener("click", function () {
console.log("document元素的click事件");
}, false);
window.addEventListener("click", function () {
console.log("window元素的click事件");
}, false); */
/* son.addEventListener("click", function () {
console.log("son元素的click事件");
}, true);
father.addEventListener("click", function () {
console.log("father元素的click事件");
}, true);
document.body.addEventListener("click", function () {
console.log("body元素的click事件");
}, true);
document.documentElement.addEventListener("click", function () {
console.log("html元素的click事件");
}, true);
document.addEventListener("click", function () {
console.log("document元素的click事件");
}, true);
window.addEventListener("click", function () {
console.log("window元素的click事件");
}, true); */
// son.onmouseover = function () {
// console.log("son元素的mouseover事件");
// }
// father.onmouseover = function () {
// console.log("father元素的mouseover事件");
// }
// document.body.onmouseover = function () {
// console.log("body元素的mouseover事件");
// }
// document.documentElement.onmouseover = function () {
// console.log("html元素的mouseover事件");
// }
// document.onmouseover = function () {
// console.log("document元素的mouseover事件");
// }
// window.onmouseover = function () {
// console.log("window元素的mouseover事件");
// }
/* son.onmouseenter = function () {
console.log("son元素的mouseenter事件");
}
father.onmouseenter = function () {
console.log("father元素的mouseenter事件");
}
document.body.onmouseenter = function () {
console.log("body元素的mouseenter事件");
}
document.documentElement.onmouseenter = function () {
console.log("html元素的mouseenter事件");
}
document.onmouseenter = function () {
console.log("document元素的mouseenter事件");
}
window.onmouseenter = function () {
console.log("window元素的mouseenter事件");
} */
</script>
</body>
</html>
二、事件委托
1.概念
事件委托又叫事件代理, 就是不给子元素绑定事件,给父辈元素绑定事件,把处理代码在父辈元素的事件中执行。 事件委托的原理是利用事件冒泡, 嵌套关系的元素,才可能会有事件冒泡, 事件委托一般用来给未来动态添加的元素绑定事件
2.使用案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
ul,
ol {
list-style: none;
}
ul,
ol {
display: flex;
}
ul li,
ol li {
margin: 10px 15px;
cursor: pointer;
}
ul li.active,
ol li.active {
color: red;
font-weight: bold;
}
</style>
</head>
<body>
<ul>
<li class="active">导航1</li>
<li>导航2</li>
<li>导航3</li>
<li>导航4</li>
<li>导航5</li>
</ul>
<script>
// 1) 获取所有的li标签
var ul = document.querySelector("ul");
var items = document.querySelectorAll("ul li");
// 2) 循环标签数组
for (var i = 0; i < items.length; i++) {
// 3) 事件绑定
items[i].onclick = function () {
for (var j = 0; j < items.length; j++) {
items[j].className = ""
}
this.className = "active";
}
}
// 创建一个li标签
var li = document.createElement("li");
li.innerHTML = "导航6";
ul.appendChild(li);
</script>
<ol>
<li class="active">导航1</li>
<li>导航2</li>
<li>导航3</li>
<li>导航4</li>
<li>导航5</li>
</ol>
<script>
// 1) 获取ol标签
var ol = document.querySelector("ol");
// 2) 父元素绑定事件
ol.onclick = function (event) {
// 获取事件源
var el = event.target;
console.dir(event);
// console.log("el:",el);
// console.dir(el);
// 判断点击的标签是否为li标签
if (el.tagName === "LI") {
for (var j = 0; j < ol.children.length; j++) {
// ol.children[j].className = "";
ol.children[j].classList.remove("active");
}
// 设置当前点击标签的类名
// el.className = "active";
el.classList.add("active");
}
}
// 创建一个li标签
var li = document.createElement("li");
li.innerHTML = "导航6";
ol.appendChild(li);
</script>
</body>
</html>
3.阻止冒泡行为
e.stopPropagation()//阻止冒泡行为