本文翻譯自jQuery Cookbook (O'Reilly 2009) 1.0 The jQuery Philosophy
jQuery的哲學是“寫更少的代碼,做更多的事情”,這一哲學可分述為三個概念:
充分理解這三個概念對於編寫jQuery代碼來說至關重要。我們來詳細看一下這三個概念。
更准確的說,是在DOM樹中定位一批元素,然後對該元素集進行操作。比如下面這個例子:首先向用戶隱藏一個<div>元素,然後向這個隱藏了的<div>元素內插入一些新文本,之後更改其屬性,最後重新顯示這個<div>元素。相應的jQuery代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <script type="text/JavaScript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> </head> <body> <div>old content</div> <script> //隱藏頁面上所有的div元素 jQuery('div').hide(); //更新所有div元素內的文本 jQuery('div').text('new content'); //在所有的div元素上添加值為updatedContent的class屬性 jQuery('div').addClass("updatedContent"); //顯示頁面上所有的div元素 jQuery('div').show(); </script> </body> </html>
我們來逐一看一下這四個jQuery語句:
上面的例子使用jQuery函數查找HTML頁面中所有的<div>元素,然後用jQuery方法對其進行操作(hide(), text(), addClass(), show())。
在調用jQuery方法的時候,按照jQuery的設計,可以對這些方法進行鏈式調用。比如,只做一次元素查找,然後在找到的元素上展開一系列操作。之前的代碼示例可以用鏈式調用重寫為一句JavaScript語句。
使用鏈式調用,可以將下面的代碼:
//隱藏頁面上所有的div元素 jQuery('div').hide(); //更新所有div元素內的文本 jQuery('div').text('new content'); //在所有的div元素上添加值為updatedContent的class屬性 jQuery('div').addClass("updatedContent"); //顯示頁面上所有的div元素 jQuery('div').show();
重寫成:
jQuery('div').hide().text('new content').addClass("updatedContent").show();
如果加上代碼縮進就是:
jQuery('div') .hide() .text('new content') .addClass("updatedContent") .show();
簡單地說,鏈式調用允許在當前選擇的元素集上,將無限個jQuery方法連在一起使用。究其實質,用jQuery方法處理的元素總會在方法處理完畢之後得到返回,因此鏈式調用可以一直繼續。jQuery的插件也是這樣設計的(返回封裝的元素集),因此使用插件並不會影響鏈式調用。
鏈式調用的另一個好處是通過只選擇一次DOM元素來節省開銷。避免遍歷DOM樹,對於網頁性能提升來說至關重要,因此需要盡可能重用或者緩存已選擇的DOM元素集。
在大多數情況下,如果使用了jQuery,那麼必定會和一個叫做“jQuery封裝”的東西打交道。換而言之,用jQuery從HTML頁面上選擇出來的元素會被封裝上一層jQuery提供的功能。我個人喜歡把這個東西叫做“封裝元素集”,因為它是一個封裝了jQuery功能的元素集合。這個封裝元素集有時包含一個DOM元素,有時包含多個,有時甚至裡面什麼都沒有。當封裝元素集為空時,在其上調用的jQuery方法/屬性不會拋出任何錯誤 — 這樣做可以避免不必要的if語句。
還是以上面的HTML代碼為例,當網頁中存在多個<div>元素的時候會怎麼樣?在下面的例子中,HTML頁面多了3個<div>元素:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <script type="text/JavaScript" src="http://ajax.googleapis.com/ajax/libs/ jquery/1.3.0/jquery.min.js"></script> </head> <body> <div>old content</div> <div>old content</div> <div>old content</div> <div>old content</div> <script> jQuery('div').hide().text('new content').addClass("updatedContent").show(); </script> </body> </html>
在上面的例子中並沒有任何表示循環的編程代碼。但奇妙的是,jQuery會掃描整個頁面,然後將所有的<div>元素放到封裝元素集中,之後對該封裝集中的每一個元素(隱式遍歷)執行代碼定義的一系列jQuery方法。比如,封裝集中的每一個元素都調用了.hide()。在上述代碼中,實際上我們使用的每一個方法(hide(), text(), addClass(), show())都在頁面中所有的div元素上起了作用,就像人為寫了一個循環方法來遍歷DOM元素一樣。上述代碼的執行結果是:頁面中的每一個<div>元素都被隱藏,更改內含文本,添加class屬性,並最終重新顯現。
熟悉封裝元素集和隱式遍歷對於編寫復雜的循環邏輯來說非常重要 — 需要留意的是,在寫任何額外的循環代碼之前,一個簡單的循環操作已經存在了(比如:jQuery(‘div').each(function(){})。換而言之,jQuery方法的調用會影響封裝元素集中的每一個元素。
需要注意的是,有一些jQuery方法的行為特殊,只會影響封裝元素集中的第一個元素(比如:attr())。