前言
网站设计的优化是一个很大的话题,有一些通用的原则,也有针对不同开发平台的一些建议。这方面的研究一直没有停止过,我在不同的场合也分享过这样的话题。
作为通用的原则,雅虎的工程师团队曾经给出过35个最佳实践。这个列表请参考 Best Practices for Speeding Up Your Web Site ( ),同时,他们还发布了一个相应的测试工具Yslow
我强烈推荐所有的网站开发人员都应该学习这些最佳实践,并结合自己的实际项目情况进行应用。 接下来的一段时间,我将结合ASP.NET这个开发平台,针对这些原则,通过一个系列文章的形式,做些讲解和演绎,以帮助大家更好地理解这些原则,并且更好地使用他们。
准备工作
为了跟随我进行后续的学习,你需要准备如下的开发环境和工具
- Google Chrome 或者firefox ,并且安装 这个扩展组件.请注意,这个组件是雅虎提供的,但目前没有针对IE的版本。
- 你应该对这些浏览器的开发人员工具有所了解,你可以通过按下F12键调出这个工具。
- Visaul Studio 2010 SP1 或更高版本,推荐使用Visual Studio 2012
- 你需要对ASP.NET的开发基本流程和核心技术有相当的了解,本系列文章很难对基础知识做普及。
本文要讨论的话题
这一篇我和大家讨论的是第二十六条原则: (设计“智能”的事件处理程序)。
我故意给“智能”两个字打上了双引号,意思是说,其实这也算不上智能,我们需要了解DOM元素的事件工作机制,就能正常地写出更好的事件处理程序。
对于DOM的事件机制,你可能自认为相当了解了,例如你能熟悉地报出不少事件的名称(例如load,unload,click,change,focus,blur等),记住他们当然是很好的,但这可不是全部。有兴趣的朋友可以看看W3C的标准文档:。这个标准文档中提到了事件流的概念(Event-flow),并且提到一种所谓的“冒泡(Bubbing)”机制。
那么,什么是“冒泡”机制呢?我们可以通过一个简单的实例来讲解。
下面是一个简单的页面定义,里面有很多个按钮,我们希望用户点击每个按钮的时候,都能弹出一个对话框,并显示当前按钮的文本。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication4.WebForm1" %>
这样做当然是没有问题的,这是最直接和“正常”的用法。但如果细想一下的话,上述的代码,其实是为每个按钮控件都绑定了一个处理程序。如果按钮有很多(例如100个),那么就需要产生100个事件的绑定。过多的事件绑定会对性能有所影响。
利用DOM事件的冒泡机制,我们可以将代码改写成下面这样:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication4.WebForm1" %>
我们看到,在这个改进的版本中,没有直接对按钮进行事件绑定,而是为它们的容器控件(DIV)做了一个事件绑定。如果你运行起来,实际上的效果和之前那一次是一样的:点击每个按钮,分别会弹出一个对话框,显示当前按钮的文本。
这是怎么回事呢?总结起来说,DOM元素的会按照下面的方式运作的:
用户点击了按钮,首先会去查找按钮上面有没有直接绑定事件处理程序,如果有的话,先执行这个事件处理程序;
然后会尝试查找按钮的上层元素是否有绑定相应的事件处理程序,如果有,则也会执行。
再往上查找,只要有相应的事件注册,都会被执行,直到最顶层的BODY为止。
这就是“冒泡”的意思。同时,这种事件机制还有一种叫法:。
一个附加的问题是:如果我们既在按钮上面订阅了事件,而且也在DIV上面订阅了事件,那么会不会同时都会被触发了。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication4.WebForm1" %>
答案是:他们都会被执行。
那么,如果我想在某些情况下,只触发按钮直接订阅的事件,而不触发DIV订阅的事件(阻止将事件冒泡),行不行呢?当然是可以的,你可以添加下面这样的代码
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication4.WebForm1" %>
所以,通过本文,我们了解到事件远非我们看到的那么简单。通过理解“冒泡”或者“事件代理”,我们可以将事件处理得更加合理。
值得一说的是,在桌面开发的WPF和Silverlight中,很多事件也同样采用了“冒泡”这样的策略,有兴趣的朋友可以参考 :