第8章 高效開發和使用外掛 (三)

mybwu_com發表於2013-12-28

8.1.13 優化 jQuery 外掛 -- 新增事件日誌

在傳統開發中,軟體都包含有事件日誌,這樣就可以在事件發生時或發生後進行跟蹤。在 JavaScript 程式除錯中,我們常常使用 alert() 方法來跟蹤程式,但是這種做法影響了程式的正常流程,不符合頻繁、實時顯示事件資訊。我們可以模仿其他軟體中的除錯臺 log() 函式,藉助這個函式將事件日誌資訊輸出到獨立的日誌檔案中,從而避免中斷頁面互動程式。

首先,我們為 jQuery 物件新增一個全域性函式 log() 。在這個函式中,將把發生的事件資訊寫入事件日誌包含框中。實現程式碼如下。

  1. jQuery.log=function(msg){
  2. varhtml=jQuery('<divclass="log"></div>').text(msg);
  3. jQuery(".logbox").append(html);
  4. };
然後,在事件中呼叫該日誌方法,從而實時跟蹤事件發生時的事件,實現程式碼如下。

  1. <scripttype="text/javascript">
  2. jQuery.log=function(msg){
  3. varhtml=jQuery('<divclass="log"></div>').text(msg);
  4. jQuery(".logbox").append(html);
  5. };
  6. $(function(){
  7. $("input").click(function(event){
  8. vare=event.type;
  9. $.log(e);
  10. });
  11. $("input").mouseover(function(event){
  12. vare=event.type;
  13. $.log(e);
  14. });
  15. $("input").mouseout(function(event){
  16. vare=event.type;
  17. $.log(e);
  18. });
  19. });
  20. </script>
  21. </head>
  22. <body>
  23. <inputtype="button"value="提交按鈕"/>
  24. <divclass="logbox"></div>
  25. </body>
但是,在一個頁面中往往會包含很多事件示例,如果分別進行記錄,會非常不方便,為此可以定義一個物件方法,而不是使用全域性函式。程式碼如下所示。

  1. (function($){
  2. $.extend($.fn,{
  3. log:function(msg){
  4. varhtml=jQuery('<divclass="log"></div>').text(msg);
  5. returnthis.each(function(){
  6. jQuery(".logbox").append(html);
  7. });
  8. }
  9. });
  10. })(jQuery);
然後在例項中呼叫該日誌方法,程式碼如下。

  1. <scripttype="text/javascript">
  2. (function($){
  3. $.extend($.fn,{
  4. log:function(msg){
  5. varhtml=jQuery('<divclass="log"></div>').text(msg);
  6. returnthis.each(function(){
  7. jQuery(".logbox").append(html);
  8. });
  9. }
  10. });
  11. })(jQuery);
  12. $(function(){
  13. $("h1").click(function(event){
  14. vare=event.type;
  15. $(this).log(this.nodeName.toLowerCase()+"."+e);
  16. });
  17. $("p").mouseover(function(event){
  18. vare=event.type;
  19. $(this).log(this.nodeName.toLowerCase()+"."+e);
  20. });
  21. $("input").mouseout(function(event){
  22. vare=event.type;
  23. $(this).log(this.nodeName.toLowerCase()+"."+e);
  24. });
  25. });
  26. </script>
  27. </head>
  28. <body>
  29. <h1>標題文字</h1>
  30. <inputtype="button"value="提交按鈕"/>
  31. <p>段落文字</p>
  32. <divclass="logbox"></div>
  33. </body>
我們還可以進一步改善 log() 日誌方法的靈活度,使其自動搜尋最近顯示日誌資訊的元素,通過利用該方法的語境,我們可以在遍歷 DOM 元素時找到距離最近的日誌元素。實現程式碼如下。

  1. <scripttype="text/javascript">
  2. (function($){
  3. $.extend($.fn,{
  4. log:function(msg){
  5. returnthis.each(function(){
  6. var$this=$(this);//獲取當前元素
  7. while($this.length){//如果存在當前元素
  8. var$logbox=$this.find(".logbox");//在當前元素內搜尋是否存在日誌元素
  9. if($logbox.length){//如果存在日誌元素
  10. varhtml=jQuery('<divclass="log"></div>').text(msg);
  11. $logbox.append(html);
  12. break;//跳出檢索
  13. }
  14. $this=$this.parent();//檢索上一級匹配元素
  15. }
  16. });
  17. }
  18. });
  19. })(jQuery);
  20. $(function(){
  21. $("h1").click(function(event){
  22. vare=event.type;
  23. $(this).log(this.nodeName.toLowerCase()+"."+e);
  24. });
  25. $("p").mouseover(function(event){
  26. vare=event.type;
  27. $(this).log(this.nodeName.toLowerCase()+"."+e);
  28. });
  29. $("input").mouseout(function(event){
  30. vare=event.type;
  31. $(this).log(this.nodeName.toLowerCase()+"."+e);
  32. });
  33. });
  34. </script>
  35. </head>
  36. <body>
  37. <h1>標題文字</h1>
  38. <inputtype="button"value="提交按鈕"/>
  39. <p>段落文字</p>
  40. <divclass="logbox"></div>
  41. </body>
最後,我們還可以改善引數的處理機制,考慮到 log() 方法只能夠簡單地接受字串型資訊,如果要向 log() 方法傳遞更多的資訊,就會變得無能為力。遵循 jQuery 框架方法的一貫設計思想,我們可以考慮允許使用者以物件列表的形式向 log() 方法傳遞更多甚至無限制的資訊。因此,我們還需對 log() 方法中的引數處理機制進行改善。如果使用者向其傳入物件型別的引數,則直接呼叫它,將會顯示 "[object object]" 的字串,顯然這並不是我們所希望的日誌資訊。

  1. (function($){
  2. $.extend($.fn,{
  3. log:function(msg){
  4. if(typeofmsg=="object"){//如果引數為物件型別,則解析該物件包含的資訊
  5. varstr="{";
  6. $.each(msg,function(name,value){//遍歷物件成員
  7. str+=name+":"+value+",";
  8. });
  9. str=str.substring(0,str.length-2);//消除最後一個成員的逗號
  10. str+="}";
  11. msg=str;//把解析的物件資訊返回給引數變數
  12. }
  13. returnthis.each(function(){
  14. var$this=$(this);//獲取當前元素
  15. while($this.length){//如果存在當前元素
  16. var$logbox=$this.find(".logbox");//在當前元素內搜尋是否存在日誌元素
  17. if($logbox.length){//如果存在日誌元素
  18. varhtml=jQuery('<divclass="log"></div>').text(msg);
  19. $logbox.append(html);
  20. break;//跳出檢索
  21. }
  22. $this=$this.parent();//檢索上一級匹配元素
  23. }
  24. });
  25. }
  26. });
  27. })(jQuery);
這樣,我們就可以在 log() 方法中傳入更多的資訊,當然也可以直接傳入字串資訊,應用示例如下所示。

  1. $(function(){
  2. $("h1").click(function(event){
  3. $(this).log({
  4. nodeName:this.nodeName.toLowerCase(),
  5. eventType:event.type
  6. });
  7. });
  8. $("p").mouseover(function(event){
  9. $(this).log({
  10. nodeName:this.nodeName.toLowerCase(),
  11. eventType:event.type
  12. });
  13. });
  14. $("input").mouseout(function(event){
  15. vare=event.type;
  16. $(this).log(this.nodeName.toLowerCase()+"."+e);
  17. });
  18. });
  19. </script>
  20. </head>
  21. <body>
  22. <h1>標題文字</h1>
  23. <inputtype="button"value="提交按鈕"/>
  24. <p>段落文字</p>
  25. <divclass="logbox"></div>
  26. </body>

8.1.14 建立 jQuery 外掛應注意的問題

由於外掛結構簡單,建立比較容易,對於初學者來說它簡單易學,對於高手來說它很靈活,因此網上共享的 jQuery 外掛數量急速上升。另外,jQuery 允許使用多種風格建立外掛,如何遵守公共規則,是很多初學者必須注意的問題。

jQuery 開發團隊制定了通用規則,為外掛使用者建立了一個通用而可信的環境。因此,建議讀者在建立外掛中遵守這些規則,確保自定義的外掛與其他程式碼和平相處,並獲得廣大使用者的認可。

建立 jQuery 外掛應注意以下幾個問題。

1.命名規則

如果希望使用者檢視檔案時能立即知道這是一個什麼外掛,統一檔名稱是必須的。我們可以遵循這樣的命名規則: jquery.plug-in_name.js 。

其中 plug-in_name 表示外掛的名稱,在這個檔案中,所有全域性函式都應該包含在名為 plug-in_name 的物件中。如果外掛只有一個函式,則可以考慮使用 jQuery.plug-in_name() 形式命名。

外掛中的物件方法可以靈活命名,但是應保持相同的命名風格。如果定義多個方法,建議在方法名前新增外掛名字首,以儲存清晰。不建議使用過於簡短的名稱,或者語義含糊的縮寫名,或者公共方法名,如 set() 、get() 等,這樣很容易與外界的方法混淆。

2.基本思想

所有新方法都附加到 jQuery.fn 物件上,所有新功能都附加到 jQuery 物件上。這是實際編碼過程中最重要的規則。

3.方法內的 this 關鍵字

在外掛方法中,this 關鍵字用於引用 jQuery 物件,這有利於外掛編寫,它讓所有外掛在引用 this 時,知道從 jQuery 接收到哪個物件。所有 jQuery 方法都是一個 jQuery 物件的環境中呼叫的,因此函式體中 this 關鍵字總是指向該函式的上下文,即 this 此時是一個包含多個 DOM 元素的陣列。

4.迭代匹配元素

使用 this.each() 迭代匹配的元素,這是一種可靠而有效地迭代物件的方式。

出於效能和穩定性考慮,推薦所有的方法都使用它迭代匹配的元素。無論 jQuery 物件實際匹配的元素有多少,所有方法都必須以適當方式執行,一般來說,應該呼叫 this.each() 方法來迭代所有匹配的元素,然後再依次操作每個 DOM 元素。

****注意:在 this.each() 方法體內,this 關鍵字就不再引用 jQuery 物件,而是引用當前匹配的 DOM 元素物件。****

5.方法返回值。

所有方法都應該返回一個值,除了特定需求方法外,所有方法都必須返回 jQuery 物件。

除了需要方法返回計算值或者某個特定物件等,一般方法都應該返回當前上下文環境中的 jQuery 物件,即 this 關鍵字引用的陣列。通過這種方式,可以保持 jQuery 框架內方法的連續行為,即方法連綴寫法。jQuery 方法的順序鏈非常著名,如果編寫打破鏈條的外掛,它就會給使用者開發帶來諸多不方便。

如果匹配的物件集合被修改,則應該通過呼叫 pushStack() 方法建立新的 jQuery 物件,並返回這個新物件,如果返回值不是 jQuery 物件,則應該明確說明。

6.方便壓縮

外掛中定義的所有方法或函式,在末尾都必須加上分號(即 ;) ,以方便程式碼壓縮。壓縮 JavaScript 檔案是最佳實踐,若大於最小值會讓自定義外掛很快就被使用者拋棄。

7.jQuery 和 $ 有區別

在外掛程式碼中總是使用 "jQuery" ,而不是 "$" 。$ 並不總是等於 jQuery ,這個很重要,如果使用者使用 var JQ = jQuery.noConflict() ;函式更改 jQuery 別名,那麼就會引發錯誤,另外其他 JavaScript 框架也可能使用 $ 別名。

在複雜的外掛中,如果全部使用 "jQuery" 代替 "$" ,又會讓人難以接受這種複雜的寫法,為了解決這個問題,建議使用如下外掛模式。

(function($){

// 在外掛包中使用 $ 代替 jQuery

})(jQuery);

這個包裝函式接受一個引數,該引數傳遞的是 jQuery 全域性物件,由於引數被命名為 $ ,因此在函式體內就可以安全使用 $ 別名,而不用擔心命名衝突。

上述這些規則在外掛程式碼中都必須遵守,如果不遵守這些外掛規則,那麼自己開發的外掛就得不到廣泛應用和推廣。因此,遵守這些規則非常重要,它不僅能保證外掛程式碼的統一性,還能增加外掛的成功機率。

相關文章