JavaScript Event学习第八章 事件的顺序(2)


document.onclick = doSomething;
if (document.captureEvents) document.captureEvents(Event.CLICK);


你在任意元素上的click时间都会冒泡到页面然后出发了这个事件处理程序。只有当前面的事件处理程序明确的阻止冒泡,才不会传递到整个页面。

使用
因为每个事件都会在整个文档上停止,默认的事件处理程序就变得可能。假设你有一个这样的页面:

复制代码 代码如下:


------------------------------------
| document |
| --------------- ------------ |
| | element1 | | element2 | |
| --------------- ------------ |

------------------------------------

element1.onclick = doSomething;
element2.onclick = doSomething;
document.onclick = defaultFunction;


现在如果用户点击了element1或者element2那么doSomething()就会执行。在这如果你愿意也可以阻止他的传播。如果不的话,那么defaultFunction()就会执行。用户在其他地方的点击也会让defaultFunction()执行。有时候这可能有用。
设置全局的事件处理程序在写拖动代码的时候就很有必要。通常一个层上的mousedow事件会选择这个层然后对mousemove事件做出回应。虽然mousedown通常注册在这个层上来避免一些浏览器的bug,但是其他的事件处理程序都必须是全局的(document-wide)。
记住浏览器逻辑的第一定律:什么都会发生的,而且经常是在你做的准备最少的时候。可能发生的是用户的鼠标疯狂的移动然后代码没有跟上导致鼠标已经不再这个层上了。
如果在某个层上注册了onmousemove事件处理程序,如果这个层不再响应鼠标的移动了,那么肯定会让用户感到迷惑。
如果某个曾上注册了onmouseup事件处理程序,那么程序会在用户松开鼠标的时候程序没有捕捉到造成这个层还在随着鼠标移动。
在这种情况下事件冒泡就很重要,因为全局的事件处理程序会保证执行的。

关掉它
但是通常你想关闭所有的相关的捕获和冒泡。另外,如果你的文档结构非常的复杂(比如一大堆复杂的表格之类)你也需要关闭冒泡来节省系统资源。要不然浏览器就得一个个的查看父元素是否有事件处理程序。虽然可能一个都没有,但是查找一样浪费时间。
在微软模式里你必须讲事件的cancelBubble属性设置为true。
window.event.cancelBubble = true
在W3C模式中你必须调用stopPropagation()方法。

e.stopPropagation()
这会阻止这个事件的冒泡阶段。阻止事件的捕获极端基本上是不可能的。我也想知道为啥。
一个完整的跨浏览器的代码如下:

复制代码 代码如下:


function doSomething(e)
{
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
}


在不支持cancelBubble的浏览器里面设置也不会有啥问题。浏览器会创建一个这样的属性。当然是没啥用的,只是为了安全。

currentTarget
我们之前讲过,一个事件包含target或者srcElement包含一个发生事件的元素的引用。在我们的例子是element2,因为用户点击了他。
理解在捕获和冒泡过程中这个target是不会改变的非常重要:他一直指向element2.
但是假设我们注册了下面的事件处理程序:

element1.onclick = doSomething;
element2.onclick = doSomething;
如果用户点击element2那么doSomething()执行了两次。那么你怎样知道那个HTML元素处理着这个事件呢?target/scrElement也不能给出答案,从事件一开始就一直指向element2.
为了解决这个问题W3C添加了currentTarget属性。它包含一个正在处理的事件的HTML元素的引用:就是我们想要的那个。不幸的是微软模式没有类似的属性。
你也可以用this关键字。在这个例子里就是指向正在处理的事件的HTML元素,就先currentTarget。

微软模式的问题
但是当你使用微软的事件注册模型,this关键字不是只想HTML元素的。然后又没有一个像currentTarget类似的属性,这就意味着如果你这么做:

element1.attachEvent('onclick',doSomething)
element2.attachEvent('onclick',doSomething)
你就不知道那个HTML元素正在处理事件。这是微软的事件注册模式最严重的问题所以就根本不要用他,即使是那些只在IE/win下的程序。
我希望微软能够尽快添加一个类似currentTarget的属性或者遵循标准?我们设计急需啊。

继续
如果你想继续学习,请看下一章。
原文地址:
我的twitter: @rehawk

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdpyxd.html