本文譯自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方法的行為特殊,只會影響封裝元素集中的第一個元素(例如:attr())。