标签:
今天在写一个demo的时候,用到了事件绑定,改BUG改了半天,后来才想明白,所以记下来
以click事件为例:
element.onclick = handler
element.addEventListener(type,handler[,useCapture])
W3C标准element.attachEvent("on"+type,handler)
对于onclick,相当于在HTML标签中添加onclick=handler
属性,所以对于一个DOM元素只能绑定一个(最后一次声明)事件,无法对一个DOM元素绑定多个事件。例:
var btn = document.getElementById("btn");
btn.onclick = handler1;
btn.onclick = handler2;
btn.onclick = handler3;
这相当于只绑定了handler3。
addEventListener属于W3C标准规范,基本语法就不介绍了。其与onclick的区别在于它是可以对DOM元素绑定多个事件的,例:
var btn = document.getElementById("btn");
btn.addEventListener("click",handler1,false);
btn.addEventListener("click",handler2,false);
btn.addEventListener("click",handler3,false);
这相当于对btn元素绑定了3个事件,执行顺序为:handler1->handler2->handler3。
非W3C标准(又是万恶的根源—IE),其作用域addEventListener类似,只不过两者的执行顺序不同(低版本),而且attachEvent没有第三个参数用于指定是否捕获(IE都是冒泡),另外在第一个参数上其前面是有’on’的。例:
var btn = document.getElementById("btn");
btn.attachEvent("onclick",handler1);
btn.attachEvent("onclick",handler2);
btn.attachEvent("onclick",handler3);
这相当于对btn元素绑定了3个事件,执行顺序为:handler3->handler2->handler1。
补充:还有一点区别是关于this值的,attachEvent
中的this是global(window),而另外两个方法是绑定的DOM元素
说了这么多,说一下我遇到的demo,完成在多行文本输入框(textarea)中输入@时,会有好友列表弹出,其位置位于键入@时的位置。不是特别难,程序流程大概就是:
对textarea添加时间监听,每当输入时就会检测是否为@,当输入@时,首先取到当前光标位置的坐标,然后将好留列表显示在该处;当用户选择点击其中一个好友之后,会把其名字插入输入框当前@之后,好友列表消失。
但是写完后发现一个BUG:当我选择其中一个好友时,其名字插入了所有的@之后 - -!
在加入console.log
输出其字符位置后发现,当点击发生时调用了多次插入好友名字事件
原因就是我把事件绑定(addEventListener
)定义在了输入@之后执行的函数内,也就是说,每当我输入一次@,就会再次定义一个eventHandler,上面说到的,对一个元素使用addEventListener
是执行多次事件,而事件中调用了父函数的光标位置变量,形成了闭包,因此输入了多少@,就会相应的执行多少次事件,将@后面的字符变为点击的好友名字。
而当我把事件绑定语句改为用onclick
后,只会执行最后一次定义的事件,因此bug消失。。。(写的有点啰嗦)
另外,在MDN上说:
多个相同的事件处理器
如果多个相同的 EventListener被注册到同一个EventTarget,而且参数都是相同的,那么重复的实例会被抛弃。所以这么做不会使得 EventListener 被调用两次,也不需要用removeEventListener手动清除多余的EventListener ,因为重复的都被自动抛弃了。
但是在我自己的测试中,还是执行了3次,并没有抛弃重复的。
HTML
<input type="button" id="btn" value="click1">
JS
var btn = document.getElementById("btn");
btn.addEventListener("click",function(event){
alert(event.target.value);
});
btn.addEventListener("click",function(event){
alert(event.target.value);
});
btn.addEventListener("click",function(event){
alert(event.target.value);
});
标签:
原文地址:http://blog.csdn.net/jhl211/article/details/51334146