1.js完整事件流
从下图可以看出一个完整的事件流是从window开始,最后回到window的一个过程
事件流被分为3个阶段:1-5捕获阶段,5-6:目标阶段,6-10:冒泡阶段
加入事件 addEventListener 移除事件 removeEventListener
<body>
<div id="div" style="height: 100px;background: grey;"></div>
</body>
<script>
var eleDiv = document.querySelector('#div');
var i = 0;
// 捕获
// 3号事件
document.body.addEventListener('click',function(){
console.log('捕获-阶段3:body')
},{
// 默认值是不使用捕获,即冒泡(这里可以去看addEventListener参数说明)
capture:true
});
// 4号 event.stopPropagation()可以阻止事件的传递(事件流任何阶段都可使用)
eleDiv.addEventListener('click',function(event){
console.log('捕获-阶段4:div')
if(i++ % 2 !== 0) {
event.stopPropagation(); // 阻止事件传递
}
},{
// 默认值是不使用捕获,即冒泡
capture:true
})
// 冒泡
// 7号事件
eleDiv.addEventListener('click',function(){
console.log('捕获-阶段7:div')
},{
// 冒泡(默认值)
capture:false
});
// 8号事件
document.body.addEventListener('click',function(){
console.log('捕获-阶段8:body')
},{
// 冒泡(默认值)
capture:false
})
</script>
2.事件委托
靠父元素body来代理其子元素div的事件
// 这里两秒后添加一个div节点
setTimeout(function(){
document.body.innerHTML += '<div id="div" class="abc" style="height: 100px;background: grey;"></div>'
},2000);
//获取div节点
var eleDiv = document.querySelector('#div');
// 由于前两秒子元素div还不存在,可以靠父元素body来代理div的事件(此刻div不存在)
// 实现的效果是点击div会移除他本身
document.body.addEventListener('click', function (event) {
console.log(this); // 固定body
console.log(event.currentTarget); // 固定body
console.log(event.target); // 实际触发事件的元素(div或者body),所以我们确定用这个来表示实际触发事件的元素
// 获取事件触发对象
var target = event.target;
if (target.classList.contains('abc')) {
console.log('找到了子元素点击的事件');
// var id = target.getAttribute('id');// 这里是获取节点id的方法
target.remove();
}
});