版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/black_hole2009/article/details/52690276
图片展示了DOM树是如何使用事件流进行事件分发:
Dom树中从最外层的Window至内层具体的html标签都可以通过addEventListener(type, listener, useCapture)方法添加监听事件。
捕获阶段(Capture Phase):
事件分发顺序是从最外层的Window开始,按照顺序:Window-Document-html-body-table-tbody-tr-td由外至内分发。
目标阶段(Target Phase):
事件分发至真正被点击的元素。
冒泡阶段(Bubbling Phase):
事件分发顺序是从最内层的td开始,按照顺序:td-tr-tbody-table-body-html-Document-Window由内往外分发,与事件捕获顺序相反。就像将一个石头扔进水里,气泡由水底向水面上浮一样。
例子:
<style>
#testDiv, #testP, #testSpan{
margin: 5px;
padding: 5px;
box-sizing: border-box;
cursor: default;
}
#testDiv{
width: 300px;
height: 300px;
border: indianred 3px solid;
}
#testP{
width: 200px;
height: 200px;
border: hotpink 3px solid;
}
#testSpan{
display: block;
width: 100px;
height: 100px;
border: orange 3px solid;
}
</style>
<body>
<div id="testDiv">testDiv
<p id="testP">testP
<span id="testSpan">testSpan</span>
</p>
</div>
</body>
<script>
var testDiv = document.getElementById("testDiv");
var testP = document.getElementById("testP");
var testSpan = document.getElementById("testSpan");
// 捕获,阶段绑定事件
window.addEventListener("click", function(e){
console.log("window 捕获,", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, true);
document.addEventListener("click", function(e){
console.log("document 捕获,", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, true);
document.documentElement.addEventListener("click", function(e){
console.log("html 捕获,", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, true);
document.body.addEventListener("click", function(e){
console.log("body 捕获,", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, true);
testDiv.addEventListener("click", function(e){
console.log("testDiv 捕获,", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, true);
testP.addEventListener("click", function(e){
console.log("testP 捕获,,", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, true);
testSpan.addEventListener("click", function(e){
console.log("testSpan 捕获,", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, true);
// 冒泡阶段绑定的事件
window.addEventListener("click", function(e){
console.log("window 冒泡", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, false);
document.addEventListener("click", function(e){
console.log("document 冒泡", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, false);
document.documentElement.addEventListener("click", function(e){
console.log("html 冒泡", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, false);
document.body.addEventListener("click", function(e){
console.log("body 冒泡", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, false);
testDiv.addEventListener("click", function(e){
console.log("testDiv 冒泡", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, false);
testP.addEventListener("click", function(e){
console.log("testP 冒泡", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, false);
testSpan.addEventListener("click", function(e){
console.log("testSpan 冒泡", "目标节点:" + e.target.nodeName, ", 当前节点:" + e.currentTarget.nodeName);
}, false);
</script>
点击testSpan标签布局的橙色方框内部,控制台的打印结果如下: