设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

生动详细解释javascript的冒泡和捕获

2013-5-11 13:33| 发布者: joejoe0332| 查看: 3443| 评论: 0|原作者: hh54188的博客|来自: 伯乐在线

摘要:   原文:Event order 翻译:hh54188的博客   前言:虽然精通jquery,但对它的原型javascript却不是很了解,最近在学习javascript中遇到了一些困难,比如冒泡和捕获,很多次被提到,但又不知究竟应用在何处。找到 ...

  一直在发生

  首先你要明白的是事件捕获或者冒泡一直在发生。如果你给整个页面文档的定义一个通用onclick处理函数

1
2
3
4
5
document.onclick = doSomething;
 
if (document.captureEvents) document.captureEvents(Event.CLICK);
 
//第二句话我也不知道什么意思,初学者,希望有能人能解释

  在页面上单击任何元素的单击事件,最终会冒泡至页面最高文档层,因此触发那个通用的处理函数,除非之前一个处理函数明确的指出终止冒泡,这样才冒泡才不会传播到整个文档层面

  用法(这一小节翻译的不好,因为没有实战,我也不是很理解,可以在留言中补充,我会更新)

  因为任何事件传播终止于页面文档(这个最高层),这使默认的事件处理函数变得可能,假设你有这样一个页面

------------------------------------
| document                         |
|   ---------------  ------------  |
|   | element1    |  | element2 |  |
|   ---------------  ------------  |
|                                  |
------------------------------------
1
2
3
element1.onclick = doSomething;
element2.onclick = doSomething;
document.onclick = defaultFunction;

  现在如果用户单击元素1或者元素2,doSomething()将被执行。如果你愿意的话,如果你不想让事件冒泡至执行 defaultFunction(),你可以在这里阻止事件冒泡向上传播,。但是如果用户点击页面上的其他部位,defaultFunction()还是 会被执行。这样的效果或许有时能用的上。

  设置页面­——使处理函数有范围较大的触发面积,在“拖拽效果”脚本中是必须的。一般来说在某一个元素层上发生 mousedown事件意味着选择了这个元素,并且使它能够响应mousemove事件。虽然mousedown通常绑定于这个元素层上以避免浏览器 bug,但是其他两者的事件函数的范围必须是整个页面(?)

  记住浏览器学的第一法则(First Law of Browserology)是:一切皆有可能(anything can happen),并且是在你起码有点准备的时候。所以有可能发生的是,用户拖拽时,大幅度在页面上移动他的鼠标,脚本却不能在大幅度中做出反应,以至于鼠 标也就不再停留在元素层上了

  • 如果onmouseover处理函数绑定在元素层上,这个元素层不会再对鼠标的移动有任何反应,这会让用户觉得奇怪
  • 如果onmouseup处理函数绑定在元素层上,事件也不能被触发,后果是,用户想放下这个元素层后,元素层持续对鼠标移动做出反应。这会引起(用户)更多的迷惑(?)

  所以在这个例子中,事件冒泡非常的有用,因为将你的处理函数放在页面层能保证他们一直能被执行

  把它给关了

  但是一般情况下,你会想关了所有的冒泡和捕获以保证函数之间不会打扰到对方。除此之外,如果你的文档结构相当的复杂(许多table之间相互嵌套或 者诸如此类),你也会为了节省系统资源,而关闭冒泡。此时浏览器不得不检查目标元素的每一  个祖先,看是否它有一个处理函数。即使一个都没有找到,刚刚的搜 索同样花费不少时间

  在微软的模型中,你必须设置事件的cancelBubble的属性为true

1
window.event.cancelBubble = true

  在w3c模型中你必须调用事件的stopPropagation()方法

1
e.stopPropagation()

  这会阻止所有冒泡向外传播。而作为跨浏览器解决方案应该这么作:

1
2
3
4
5
6
7
8
9
10
function doSomething(e)
 
{
     if (!e) var e = window.event;
 
e.cancelBubble = true;
 
if (e.stopPropagation) e.stopPropagation();
 
}

  在支持cancelBubble属性的浏览器中设置cancelBubble无伤大雅。浏览器会耸一耸肩然后创造一个这个属性。当然这也并不能真正的取消冒泡,但至少能保证这条命令是安全正确的

currentTarget

  像我们之前看到的一样,一个事件用target或者是srcElement属性用来表示事件究竟发生在哪个目标元素上(即用户最初点击的元素)。在我们的例子中是元素2,因为我们单击了它。

  非常重要的是,要明白在捕获或者冒泡阶段的目标元素是不变的,它始终与元素2相关联。

  但是假设我们绑定了以下函数

1
2
3
element1.onclick = doSomething;
 
element2.onclick = doSomething;

  如果用户单击元素2, doSomething()会被执行两次。但是你怎么知道哪个html元素正在响应这个事件?target/srcElement也没有给出线索,但人们总是更倾向于元素2,因为它是引起事件的原因(因为用户点击的是它)。

  为了解决这个问题,w3c 增加了currentTarget这个属性,它就指向正在处理事件的元素:这恰是我们需要的。很不幸的是微软模型中并没有相似的属性

  你也可以使用”this”关键字。在上面的例子中,它相当于正在处理事件的html元素,就像currentTarget。

  微软模型的问题

  但是当你使用微软事件绑定模型时,this关键字并不相当于HTML元素。联想缺少类似currentTarget属性的微软模型(?)——按上面的代码操作的话,你这么做便意味着:

1
2
3
element1.attachEvent('onclick',doSomething)
 
element2.attachEvent('onclick',doSomething)

  你无法确切知道哪一个HTML元素正在负责处理事件,这是微软事件绑定模型最严重的问题,对我来说,这也是我从不使用它的原因,哪怕是在开发仅供Windows下的IE的应用程序

  我希望能够尽快增加currentTarget类似的属性——或者遵循标准?web开发者们需要这些信息

  后记:

  因为没有实战过javascript,所以这篇文章有些地方我并不是很理解,只能硬生的翻译出来,比如谈拖拽效果的那一段,如果大家有什么补充和疑问可以留言给我,谢谢支持啦!


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部