如何给一个元素绑定事件,分别有几种方式?各有什么好处?
- 监听方法绑定方式
事件冒泡 事件捕获
js事件流是先由 window->document->body->div->(text) 触发一遍捕获 capture ,
再由(text)->div->body->document->window触发一遍冒泡bubbling
element.addEventListener(type, listener, useCapture);
type:事件类型
listener:监听方法
useCapture:是否捕获,默认false,即在冒泡时触发
listener的入参event可以获取到event.target event.currentTarget
其中,target是真正发生事件的DOM元素,而currentTarget是当前事件发生在哪个DOM元素上。
优点:
- 同时支持捕获和冒泡
- 可以同时绑定多个事件
缺点:
- 旧的IE不支持,需要用attachEvent替代 element.attachEvent(‘onclick’, function(){})
- IE只支持冒泡
- 在IE中,this指向window对象而不是当前元素,获取event需要获取window.event
- 直接绑定事件方式
target.onclick = function(){}
缺点:
- 只会在事件冒泡中运行,
- 一个元素一次只能绑定一个事件处理函数,
- 新绑定的事件处理函数会覆盖旧的
- 事件对象参数(event)仅非IE浏览器可用
优点:
- 在不同浏览器中表现一致
- this指向当前元素
- 直接在元素里使用事件属性
实现一个事件委托(事件代理)
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能。
事件委托示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37<ul id="ul1">
<li id="li1">111</li>
<li id="li2">222</li>
<li id="li3">333</li>
<li id="li4">444</li>
</ul>
<script>
// 非事件委托
window.onload = function(){
var oUl = document.getElementById("ul1");
var aLi = oUl.getElementsByTagName('li');
for(var i=0;i<aLi.length;i++){
aLi[i].onclick = function(){
// do something
...
}
}
}
</script>
<script>
// 事件委托
window.onload = function(){
var oUl = document.getElementById("ul1");
oUl.onclick = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == 'li'){
switch(target.id) {
case 'li1':
// do something
break;
...
}
}
}
}
</script>
event 中的 target 和 currentTarget 有什么区别?
currentTarget当前所绑定事件的元素
target当前被点击的元素