本文翻译自jQuery Cookbook (O'Reilly 2009) 1.0 The jQuery Philosophy
jQuery的哲学是“写更少的代码,做更多的事情”,这一哲学可分述为三个概念:
- 用CSS选择器查找元素,并通过jQuery方法来操作这些元素
- 在元素集上链式调用多个jQuery方法
- jQuery封装与隐式遍历
充分理解这三个概念对于编写jQuery代码来说至关重要。我们来详细看一下这三个概念。
查找元素并进行操作
更准确的说,是在DOM树中定位一批元素,然后对该元素集进行操作。比如下面这个例子:首先向用户隐藏一个
<SPAN class=dec><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><html></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><head></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><script</SPAN><SPAN class=pln> </SPAN><SPAN class=atn>type</SPAN><SPAN class=pun>=</SPAN><SPAN class=atv>"text/JavaScript"</SPAN><SPAN class=pln> </SPAN><SPAN class=atn>src</SPAN><SPAN class=pun>=</SPAN><SPAN class=atv>"http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"</SPAN><SPAN class=tag>></script></SPAN><SPAN class=pln> </SPAN><SPAN class=tag></head></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><body></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><div></SPAN><SPAN class=pln>old content</SPAN><SPAN class=tag></div></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><script></SPAN><SPAN class=pln> </SPAN><SPAN class=com>//隐藏页面上所有的div元素</SPAN><SPAN class=pln> jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>hide</SPAN><SPAN class=pun>();</SPAN><SPAN class=pln> </SPAN><SPAN class=com>//更新所有div元素内的文本</SPAN><SPAN class=pln> jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>text</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'new content'</SPAN><SPAN class=pun>);</SPAN><SPAN class=pln> </SPAN><SPAN class=com>//在所有的div元素上添加值为updatedContent的class属性</SPAN><SPAN class=pln> jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>addClass</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>"updatedContent"</SPAN><SPAN class=pun>);</SPAN><SPAN class=pln> </SPAN><SPAN class=com>//显示页面上所有的div元素</SPAN><SPAN class=pln> jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>show</SPAN><SPAN class=pun>();</SPAN><SPAN class=pln> </SPAN><SPAN class=tag></script></SPAN><SPAN class=pln> </SPAN><SPAN class=tag></body></SPAN><SPAN class=pln> </SPAN><SPAN class=tag></html></SPAN>
我们来逐一看一下这四个jQuery语句:
- 隐藏页面上所有的div元素,让它们变得不可见
- 用新文本('new content')来替换隐藏的div元素中的原有文本
- 向div元素添加新的class属性值(updatedContent)
- 在页面上重新显示div元素
上面的例子使用jQuery函数查找HTML页面中所有的
链式调用
在调用jQuery方法的时候,按照jQuery的设计,可以对这些方法进行链式调用。比如,只做一次元素查找,然后在找到的元素上展开一系列操作。之前的代码示例可以用链式调用重写为一句JavaScript语句。
使用链式调用,可以将下面的代码:
<SPAN class=com>//隐藏页面上所有的div元素</SPAN><SPAN class=pln> jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>hide</SPAN><SPAN class=pun>();</SPAN><SPAN class=pln> </SPAN><SPAN class=com>//更新所有div元素内的文本</SPAN><SPAN class=pln> jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>text</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'new content'</SPAN><SPAN class=pun>);</SPAN><SPAN class=pln> </SPAN><SPAN class=com>//在所有的div元素上添加值为updatedContent的class属性</SPAN><SPAN class=pln> jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>addClass</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>"updatedContent"</SPAN><SPAN class=pun>);</SPAN><SPAN class=pln> </SPAN><SPAN class=com>//显示页面上所有的div元素</SPAN><SPAN class=pln> jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>show</SPAN><SPAN class=pun>();</SPAN>
重写成:
<SPAN class=pln>jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>hide</SPAN><SPAN class=pun>().</SPAN><SPAN class=pln>text</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'new content'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>addClass</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>"updatedContent"</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>show</SPAN><SPAN class=pun>();</SPAN>
如果加上代码缩进就是:
<SPAN class=pln>jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>)</SPAN><SPAN class=pln> </SPAN><SPAN class=pun>.</SPAN><SPAN class=pln>hide</SPAN><SPAN class=pun>()</SPAN><SPAN class=pln> </SPAN><SPAN class=pun>.</SPAN><SPAN class=pln>text</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'new content'</SPAN><SPAN class=pun>)</SPAN><SPAN class=pln> </SPAN><SPAN class=pun>.</SPAN><SPAN class=pln>addClass</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>"updatedContent"</SPAN><SPAN class=pun>)</SPAN><SPAN class=pln> </SPAN><SPAN class=pun>.</SPAN><SPAN class=pln>show</SPAN><SPAN class=pun>();</SPAN>
简单地说,链式调用允许在当前选择的元素集上,将无限个jQuery方法连在一起使用。究其实质,用jQuery方法处理的元素总会在方法处理完毕之后得到返回,因此链式调用可以一直继续。jQuery的插件也是这样设计的(返回封装的元素集),因此使用插件并不会影响链式调用。
链式调用的另一个好处是通过只选择一次DOM元素来节省开销。避免遍历DOM树,对于网页性能提升来说至关重要,因此需要尽可能重用或者缓存已选择的DOM元素集。
jQuery封装
在大多数情况下,如果使用了jQuery,那么必定会和一个叫做“jQuery封装”的东西打交道。换而言之,用jQuery从HTML页面上选择出来的元素会被封装上一层jQuery提供的功能。我个人喜欢把这个东西叫做“封装元素集”,因为它是一个封装了jQuery功能的元素集合。这个封装元素集有时包含一个DOM元素,有时包含多个,有时甚至里面什么都没有。当封装元素集为空时,在其上调用的jQuery方法/属性不会抛出任何错误 — 这样做可以避免不必要的if语句。
还是以上面的HTML代码为例,当网页中存在多个
<SPAN class=dec><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><html></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><head></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><script</SPAN><SPAN class=pln> </SPAN><SPAN class=atn>type</SPAN><SPAN class=pun>=</SPAN><SPAN class=atv>"text/JavaScript"</SPAN><SPAN class=pln> </SPAN><SPAN class=atn>src</SPAN><SPAN class=pun>=</SPAN><SPAN class=atv>"http://ajax.googleapis.com/ajax/libs/ jquery/1.3.0/jquery.min.js"</SPAN><SPAN class=tag>></script></SPAN><SPAN class=pln> </SPAN><SPAN class=tag></head></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><body></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><div></SPAN><SPAN class=pln>old content</SPAN><SPAN class=tag></div></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><div></SPAN><SPAN class=pln>old content</SPAN><SPAN class=tag></div></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><div></SPAN><SPAN class=pln>old content</SPAN><SPAN class=tag></div></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><div></SPAN><SPAN class=pln>old content</SPAN><SPAN class=tag></div></SPAN><SPAN class=pln> </SPAN><SPAN class=tag><script></SPAN><SPAN class=pln> jQuery</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'div'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>hide</SPAN><SPAN class=pun>().</SPAN><SPAN class=pln>text</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>'new content'</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>addClass</SPAN><SPAN class=pun>(</SPAN><SPAN class=str>"updatedContent"</SPAN><SPAN class=pun>).</SPAN><SPAN class=pln>show</SPAN><SPAN class=pun>();</SPAN><SPAN class=pln> </SPAN><SPAN class=tag></script></SPAN><SPAN class=pln> </SPAN><SPAN class=tag></body></SPAN><SPAN class=pln> </SPAN><SPAN class=tag></html></SPAN>
在上面的例子中并没有任何表示循环的编程代码。但奇妙的是,jQuery会扫描整个页面,然后将所有的
熟悉封装元素集和隐式遍历对于编写复杂的循环逻辑来说非常重要 — 需要留意的是,在写任何额外的循环代码之前,一个简单的循环操作已经存在了(比如:jQuery(‘div').each(function(){})。换而言之,jQuery方法的调用会影响封装元素集中的每一个元素。
需要注意的是,有一些jQuery方法的行为特殊,只会影响封装元素集中的第一个元素(比如:attr())。