本文譯自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())。