浏览器 - 事件流
一、浏览器 事件
1、事件流
事件流 描述的是从页面中接受事件的顺序。事件流 分为两种: 事件捕获 和 事件冒泡
2、addEventListener
EventTarget.addEventListener() 方法是将指定的监听器注册到事件目标上,当该对象触发指定的事件时,指定的回调函数就会被执行。
事件目标可以是一个文档上的元素 Element, Document和 Window 或者任何其他支持事件的对象。
addEventListener() 有三个参数,
第一个参数是事件类型,
第二个参数是一个函数,作为事件触发的函数。
第三个参数是一个布尔类型,是用来空值事件冒泡或者事件捕获的。 true: 事件捕获;false: 事件冒泡。第三个参数是可选的,默认是 false。
3、事件捕获
事件捕获 是Netscape团队提出的事件流。事件从最外层元素的事件开始,一级一级地传播到事件发生的具体元素。
Example:
<body id="body">
<div id="s1">
s1
<div id="s2">s2</div>
</div>
<script>
s1.addEventListener("click",function(e) {
console.log("s1 捕获事件");
}, true);
s2.addEventListener("click",function(e) {
console.log("s2 捕获事件");
}, true);
body.addEventListener("click", function(e) {
console.log("body级 捕获事件");
}, true)
</script>
</body>
点击 s2, 事件的执行顺序是: body -> S1 -> S2 。
4、事件冒泡
事件冒泡 是IE的事件流。 事件从事件开始的具体元素开始,一级一级朝着外部元素传播事件。
我们拿上面的事件捕获的例子距离,我们只需要把addEventListener()的第三个参数修改成 false。
Example:
<body id="body">
<div id="s1">
s1
<div id="s2">s2</div>
</div>
<script>
s1.addEventListener("click",function(e) {
console.log("s1 冒泡事件");
}, false);
s2.addEventListener("click",function(e) {
console.log("s2 冒泡事件");
}, false);
body.addEventListener("click", function(e) {
console.log("body级 冒泡事件");
}, false)
</script>
</body>
点击 s2,事件的执行顺序:S2 -> S1 -> body。
5、DOM事件流
"DOM2级事件" 事件总共分三个阶段:事件捕获阶段、目标阶段、事件冒泡阶段

Example:
<body>
<div>
<p id="parEle">
我是父元素
<span id="sonEle">
我是子元素
<span id="grandson">我是孙子元素</span>
</span>
</p>
</div>
</body>
<script type="text/javascript">
var sonEle = document.getElementById('sonEle');
var parEle = document.getElementById('parEle');
parEle.addEventListener('click', function () {
console.log('父级 冒泡');
}, false);
parEle.addEventListener('click', function () {
console.log('父级 捕获');
}, true);
sonEle.addEventListener('click', function () {
console.log('子级冒泡');
}, false);
sonEle.addEventListener('click', function () {
console.log('子级捕获');
}, true);
grandson.addEventListener('click', function () {
console.log('孙子级冒泡');
}, false);
grandson.addEventListener('click', function () {
console.log('孙子级捕获');
}, true);
</script>
上面这个例子的执行顺序是: 父级捕获 -> 子集捕获 -> 孙子级冒泡 -> 孙子级捕获 -> 子级冒泡 -> 父级冒泡 。
在捕获阶段又在冒泡阶段调用事件处理程序时:事件按DOM事件流的顺序执行事件处理程序。
且当事件处于目标阶段时,事件调用顺序决定于绑定事件的书写顺序。
像上面的例子,如果将 孙子级两个事件互换位置,那么就会先执行捕获事件,再执行冒泡事件。
阻止冒泡事件的方法: e.stopPropagation()
阻止默认事件的方法: e.preventDefault()
6、target vs currentTarget 的区别
刚看到这个我查了一下。target 返回的是触发事件的元素,currentTarget 返回的是绑定事件的元素。
但是这样看起来并不是很清晰,举个例子:
<body id="father" onclick="myFunction(event)">
<p id="child" onclick="myFunction(event)">Click on child</p>
</body>
<script>
function myFunction(event) {
console.log(`currentTarget: ${event.currentTarget.id}, target: ${event.target.id}`);
}
</script>
当点击child元素的时候,因为浏览器的冒泡事件先执行child元素的点击事件,之后执行 parent 元素的点击事件。
事件的输出:
currentTarget: child, target: child currentTarget: father, target: child
可以看出,child 元素的点击事件中的 currentTarget 和 target 都是 child 元素本身。
冒泡到 father 元素之后,当前执行绑定事件元素则变为 father,因此 currentTarget 是 father;而触发事件的元素依旧是 child,所以 target 是 child。

浙公网安备 33010602011771号