本篇文章主要来讲讲 事件的冒泡机制 和 添加事件的几种方法。
一. JS的时间传递顺序: 捕获阶段 -> 目标阶段 -> 冒泡阶段
- 捕获阶段是指从父层往子层找。比如
<body><div></div></body>
,我们会先找到 body,然后下一个才是 div。就像中央领导发布政策一样。 从上往下通知。 - 目标阶段就是找到目标的那段时间,这个我们暂且不谈。
- 冒泡阶段就是从子层往外层传。比如
<body><div></div></body>
,这个时候是先写 div ,再找 body。往外依次冒泡。从内往外通知。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div2">
<div id="div1">
点我
</div>
</div>
</body>
<script type="text/javascript">
var div1 = document.getElementById('div1'),
div2 = document.getElementById('div2');
div1.addEventListener('click', function(event) {
console.log("A");
}, true);
div2.addEventListener('click', function(event) {
console.log("B");
});
div1.addEventListener('click', function(event) {
console.log("C")
}, false);
div2.addEventListener('click', function(event) {
console.log("D");
}, true);
</script>
</html>
答案是: DACB
1.我们的 addEventListener 默认的第三个参数是 false。false代表的是在冒泡阶段触发。true代表在捕获阶段触发。
2.因为第一个和第四个函数都是true,所以它们会先被触发,而 div1是被包在 div2 里面的,所以,先触发的会是 div2的,所以是 DA。
之后进入冒泡阶段,从内往外,第二个和第三个函数这个时候的顺序是 : CB
二. 兼容性地添加 JS 事件
如果我们要给按钮添加事件,我们会怎么做呢?
也许我们会这么做<button onclick="console.log('1')">点我</button>
很明显地,它破坏了标签。我们应该让 html 和 事件分离,否则,我们下一次要修改这个按钮就不好操作了。
1.耦合度太高。- 所以我们这样
const oBtn = document.getElementsByTagName('button')[0];
oBtn.onclick = function() {
console.log('1');
}
然后,当我们要添加多个 事件的时候,可能就带来了问题。
const oBtn = document.getElementsByTagName('button')[0];
oBtn.onclick = function() {
console.log('1');
}
oBtn.onclick = function() {
console.log('我是第二次');
}
2.被覆盖了。
- 所以我们改成了这样
const oBtn = document.getElementsByTagName('button')[0];
// addEventListener
oBtn.addEventListener("click", () => {console.log('1')});
oBtn.addEventListener("click", () => {console.log('我是第二次')} );
上面的执行顺序为 1 -> 第二次。很好,但是
3.IE7/8上报错了。IE没有addEventListener
- 所以我们改成了这样
var oBtn = document.getElementsByTagName('button')[0];
function addEvent(ele, event, fn) {
if (ele.addEventListener) {
ele.addEventListener(event, fn, false)
} else if (ele.attachEvent('on' + event, fn));
}
addEvent(oBtn, 'click', function(){console.log('1')})
addEvent(oBtn, 'click' , function(){console.log('第二次')});