【原创翻译】深入理解javascript事件处理函数绑定三部曲(三)——高级事件函数绑定模型
在这一篇中我将解释两种更高级的事件绑定模型:W3C和微软。又因为没有一种真正跨浏览器的,所以,至少现在,并不赞成使用它们。
W3C和微软都开发了它们自己的事件绑定模型,用来取代Netscape的传统模型。我对微软的模型颇为不爽,但是W3C的除了一点小瑕疵外还是不错的,可不幸的是很少的浏览器支持它。
w3c
w3c的DOM level2对传统模型中出现的问题都给予了特别的注意。它提供了一种简单的绑定方式,你可以在同一个元素上绑定随意数量的处理函数
w3c事件绑定模型的关键在于它的addEventListener()方法。你需要传入三个参数:事件类型,需要执行的函数,和一个布尔值(true or false),我随后会解释关于这个布尔值的含义。比如说给onclick绑定我们熟悉的不能在熟悉的doSomething()函数,你可以这么做:
element.addEventListener('click',doSomething,false)
这个模型的美妙之处,在于我们可以许许多多事件监听(event listener)给想要的元素,如果我们把上一篇的例子拿来使用,应该这样写:
element.addEventListener('click',startDragDrop,false)
element.addEventListener('click',spyOnUser,false)
当用户点击元素时两个处理函数都会被触发。请注意W3C模型并没有注明哪一个处理函数会首先被触发,所以你不能直接假设startDragDrop()会先于spyOnUser()执行。
如果想要移除处理函数,则要使用removeEventListener()方法。你可以选择移除哪一个处理函数,如:
element.removeEventListener('click',spyOnUser,false)
删除第二个函数但是留下第一个。太棒了,它正好解决了在传统模型中我们遇到的麻烦。
匿名函数
你也可以在W3C模型中使用匿名函数
element.addEventListener('click',function () {
this.style.backgroundColor = '#cc0000'
},false)
true or false
true 或者是false是addEventListener最后一个参数,它意味着处理函数是在捕获阶段还是冒泡阶段执行。如果你不确定的话,使用false吧(冒泡)
this
在javascript中,this关键字是对某个函数“拥有者”的引用。在事件处理函数中它非常的有用,是对正在处理事件的html元素的引用,以至于你可以很轻松的对他进行访问。
不幸的是尽管this关键字非常强大,但如果你不是非常清楚它的工作原理的话,它也非常难使用。我在另一篇文章中有讨论
在W3C模型中,它和传统模型中工作原理是相同的,是对正在处理事件的html元素的引用。
element.addEventListener('click',doSomething,false);
another_element.addEventListener('click',doSomething,false);
function doSomething() {
this.style.backgroundColor = '#cc0000';
}
如果给任意一个html元素的click事件绑定了一个doSomething()函数,则当用户点击它时它会变成红色背景
哪一个函数被绑定?
W3C绑定模型的问题之一就是你没办法找出已经给某个元素绑定的处理函数。在传统模型中你可以这么做:
alert(element.onclick)
你可以看到绑定给它的函数,如果提示是undefined的话表示什么都没有注册。在最近的DOM Level 3 Events中W3C新增了eventListenerList来存储现阶段被绑定的函数。这个功能还没有被所有的浏览器支持,它太新了(译者注:就当是情况而已)。无论如何,这个问题还是被解决了。
幸运的是,如果你想移除一个并没有绑定的函数,removeEventListener()并不会给出错误提示,所以你可以肆无忌惮的使用removeEventListener()
微软
微软同样开发了一套自己的绑定模型。看上去和W3C 的很像,但是有一些严重的缺陷。
想要绑定一个处理函数:把它attach给一个元素:
element.attachEvent('onclick',doSomething)
或者你需要两个处理函数:
element.attachEvent('onclick',startDragDrop)
element.attachEvent('onclick',spyOnUser)
移除一个也很简单:
element.detachEvent('onclick',spyOnUser)
缺陷
如果和W3C模型比较,微软模型有两个严重的缺陷:
- 事件总是冒泡的,没有捕获的可能性
- 处理函数总是被引用,而非复制。所以其中的this关键字总是指向window,一点用都没有。
这两个弱点会导致当一个事件冒泡时,是不可能知道哪一个html元素正在处理事件,我会在另一篇文章中详细解释
因为微软模型只在IE5或者更高版本中支持,所以它不能夸浏览器。但是即使是在IE中,也最好别使用它,因为冒泡问题在一些复杂的应用中会变得相当棘手