首先展现我们的操作页面的搭建,我们从其触发顺序来得知事件捕获和事件冒泡的原理。
<div>
<div id="a">
<div id="b">
<div id="c"></div>
</div>
</div>
</div>
然后分别对#a,#b,#c绑定click事件
<script>
document.getElementById('a').addEventListener('click',function () {
console.log(1)
},true);
document.getElementById('b').addEventListener('click',function () {
console.log(2)
},true);
document.getElementById('c').addEventListener('click',function () {
console.log(3)
},true);
document.getElementById('a').addEventListener('click',function () {
console.log(6)
},false);
document.getElementById('b').addEventListener('click',function () {
console.log(5)
},false);
document.getElementById('c').addEventListener('click',function () {
console.log(4)
},false);
</script>
点击c
输出:1->2->3->4->5->6
true的时候,属于事件捕获:从外到里触发;
事件捕获都是从window->document->html->body->div#a->div#b->div#c
false的时候,属于事件冒泡:从里到外触发
事件对象:
document.getElementById("a").addEventListener('click',function (e) {
console.log(e);
})
浏览器在触发click事件时包装一个对象,里面是事件的信息。从回调中返回。
事件委托:
<body>
<ul id="ul">
<li>吃饭</li>
<li>睡觉</li>
<li>打球</li>
<li>洗澡</li>
</ul>
<input type="'text" id="input">
<button id="btn">add</button>
<script>
var list = document.querySelectorAll('#ul li');
console.log(list);
for(var i = 0,len = list.length;i < len;i++){
list[i].addEventListener('click',function () {
alert(this.innerHTML)
},false)
}
document.querySelector('#btn').addEventListener('click',function () {
var text = document.querySelector('#input').value;
var li = document.createElement('li')
li.innerHTML = text;
li.addEventListener('click',function () {
alert(this.innerHTML)
})
document.querySelector('#ul').appendChild(li);
},false)
</script>
</body>
在我添加的这个li中,还需要给他绑定事件,如果有成百上千的要添加,就太繁琐了吧。
由此就有事件委托。
jQuery实现事件代理:
$('#ul').click('#ul li',function () {
alert(1);
})
$('#btn').click(function () {
$('#ul').append('<li>adasda</li>')
})
这样动态添加的li是直接绑定着事件的。
我们来看看其实现:
document.querySelector('#ul').addEventListener('click',function (e) {
console.log(e.target);
})
//<li>洗澡</li>
arget就是实际捕获的元素。
事件有三个阶段:捕获,目标,冒泡。
实现一个on,来实现事件代理
function on(ele, type, selector,fn) {
if(fn === undefined){
fn = selector;//表示selector没有传,比如on(ele,'click',function(){}),就把selector部分直接赋值给fn代替
selector = null;
}
ele.addEventListener(type,function (e) {
if(selector){//如果true,就需要事件代理
if(e.target.matches(selector)) fn.call(e.target,e);//e.target和selector去匹配,匹配到的话,就去执行fn。把e.target作为this传给fn,然后把事件对象e传递过去。这就完成了事件代理
return;
}
fn.call(e.currentTarget,e);
// fn(e);
})
}
on(document.querySelector('#ul'),'click','li',function (e) {
console.log(this);
})
// // 假如不传li,this的指向就是window,所以对上面进行修改
// on(document.querySelector('#ul'),'click',function (e) {
// console.log(this);
// })