1. 程式人生 > >什麼?你還不會寫JQuery 外掛

什麼?你還不會寫JQuery 外掛

前言  

如今做web開發,jquery 幾乎是必不可少的,就連vs神器在2010版本開始將Jquery 及ui 內建web專案裡了。至於使用jquery好處這裡就不再贅述了,用過的都知道。今天我們來討論下jquery的外掛機制,jquery有著成千上萬的第三方外掛,有時我們寫好了一個獨立的功能,也想將其與jquery結合起來,可以用jquery鏈式呼叫,這就要擴充套件jquery,寫成外掛形式了,如下面就是一個簡單擴充套件Jquery物件的demo:

複製程式碼
        //sample:擴充套件jquery物件的方法,bold()用於加粗字型。
        (function ($) {
            $.fn.extend({
                
"bold": function () { ///<summary> /// 加粗字型 ///</summary> return this.css({ fontWeight: "bold" }); } }); })(jQuery);
複製程式碼

呼叫方式:

這是一個非常簡單的擴充套件。接下來我們一步步來解析上面的程式碼。

一、jquery的外掛機制

為了方便使用者建立外掛,jquery提供了jQuery.extend()和jQuery.fn.extend()方法。

1. jQuery.extend() 方法有一個過載。

  jQuery.extend(object) ,一個引數的用於擴充套件jQuery類本身,也就是用來在jQuery類/名稱空間上增加新函式,或者叫靜態方法,例如jQuery內建的 ajax方法都是用jQuery.ajax()這樣呼叫的,有點像 “類名.方法名” 靜態方法的呼叫方式。下面我們也來寫個jQuery.extend(object)的例子:

複製程式碼
        //擴充套件jQuery物件本身
        jQuery.extend({
            "minValue": function (a, b) {
                
///<summary> /// 比較兩個值,返回最小值 ///</summary> return a < b ? a : b; }, "maxValue": function (a, b) { ///<summary> /// 比較兩個值,返回最大值 ///</summary> return a > b ? a : b; } }); //呼叫 var i = 100; j = 101; var min_v = $.minValue(i, j); // min_v 等於 100 var max_v = $.maxValue(i, j); // max_v 等於 101
複製程式碼

過載版本:jQuery.extend([deep], target, object1, [objectN])

   用一個或多個其他物件來擴充套件一個物件,返回被擴充套件的物件。
   如果不指定target,則給jQuery名稱空間本身進行擴充套件。這有助於外掛作者為jQuery增加新方法。 
   如果第一個引數設定為true,則jQuery返回一個深層次的副本,遞迴地複製找到的任何物件。否則的話,副本會與原物件共享結構。 
   未定義的屬性將不會被複制,然而從物件的原型繼承的屬性將會被複制。
引數
   deep:       可選。如果設為true,則遞迴合併。
   target:     待修改物件。
   object1:   待合併到第一個物件的物件。
   objectN:   可選。待合併到第一個物件的物件。
示例1:
合併 settings 和 options,修改並返回 settings。
var settings = { validate: false, limit: 5, name: "foo" }; 
var options = { validate: true, name: "bar" }; 
jQuery.extend(settings, options);
結果:
settings == { validate: true, limit: 5, name: "bar" }

示例2:
合併 defaults 和 options, 不修改 defaults。
var empty = {}; 
var defaults = { validate: false, limit: 5, name: "foo" }; 
var options = { validate: true, name: "bar" }; 
var settings = jQuery.extend(empty, defaults, options);
結果:
settings == { validate: true, limit: 5, name: "bar" } 
empty == { validate: true, limit: 5, name: "bar" }
這個過載的方法,我們一般用來在編寫外掛時用自定義外掛引數去覆蓋外掛的預設引數。

jQuery.fn.extend(object)擴充套件 jQuery 元素集來提供新的方法(通常用來製作外掛)。

首先我們來看fn 是什麼東西呢。檢視jQuery程式碼,就不難發現。

jQuery.fn = jQuery.prototype = {

   init: function( selector, context ) {.....};
};

原來 jQuery.fn = jQuery.prototype,也就是jQuery物件的原型。那jQuery.fn.extend()方法就是擴充套件jQuery物件的原型方法。我們知道擴充套件原型上的方法,就相當於為物件新增”成員方法“,類的”成員方法“要類的物件才能呼叫,所以使用jQuery.fn.extend(object)擴充套件的方法, jQuery類的例項可以使用這個“成員函式”。jQuery.fn.extend(object)和jQuery.extend(object)方法一定要區分開來。

二、自執行的匿名函式/閉包

     1. 什麼是自執行的匿名函式?     
     它是指形如這樣的函式: (function {// code})();
    2. 疑問 為什麼(function {// code})();可以被執行, 而function {// code}();卻會報錯?
    3. 分析     
       (1). 首先, 要清楚兩者的區別:     (function {// code})是表示式, function {// code}是函式宣告.     
       (2). 其次, js"預編譯"的特點:     js在"預編譯"階段, 會解釋函式宣告, 但卻會忽略表式.     
       (3). 當js執行到function() {//code}();時, 由於function() {//code}在"預編譯"階段已經被解釋過, js會跳過function(){//code}, 試圖去執行();, 故會報錯;     
    當js執行到(function {// code})();時, 由於(function {// code})是表示式, js會去對它求解得到返回值, 由於返回值是一 個函式, 故而遇到();時, 便會被執行.

   另外, 函式轉換為表示式的方法並不一定要靠分組操作符(),我們還可以用void操作符,~操作符,!操作符……

  例如:
   bootstrap 框架中的外掛寫法:
   !function($){
  //do something;
   }(jQuery);

   和 
   (function($){
  //do something;
   })(jQuery); 是一回事。

匿名函式最大的用途是建立閉包(這是JavaScript語言的特性之一),並且還可以構建名稱空間,以減少全域性變數的使用。
例如:
     var a=1;
     (function()(){
    var a=100;
  })();
      alert(a); //彈出 1
更多 閉包和匿名函式 可檢視 Javascript的匿名函式與自執行 這篇文章。

三、一步一步封裝JQuery外掛

接下來我們一起來寫個高亮的jqury外掛
1.定一個閉包區域,防止外掛"汙染"

//閉包限定名稱空間
(function ($) {
    
})(window.jQuery);

2.jQuery.fn.extend(object)擴充套件jquery 方法,製作外掛

複製程式碼
//閉包限定名稱空間
(function ($) {
    $.fn.extend({
        "highLight":function(options){
            //do something
        }
    });
})(window.jQuery);
複製程式碼

3.給外掛預設引數,實現 外掛的功能

複製程式碼
//閉包限定名稱空間
(function ($) {
    $.fn.extend({
        "highLight": function (options) {
            var opts = $.extend({}, defaluts, options); //使用jQuery.extend 覆蓋外掛預設引數
            this.each(function () {  //這裡的this 就是 jQuery物件
                //遍歷所有的要高亮的dom,當呼叫 highLight()外掛的是一個集合的時候。
                var $this = $(this); //獲取當前dom 的 jQuery物件,這裡的this是當前迴圈的dom
                //根據引數來設定 dom的樣式
                $this.css({
                    backgroundColor: opts.background,
                    color: opts.foreground
                });
            });

        }
    });
    //預設引數
    var defaluts = {
        foreground: 'red',
        background: 'yellow'
    };
})(window.jQuery);
複製程式碼

到這一步,高亮外掛基本功能已經具備了。呼叫程式碼如下:

$(function () {
    $("p").highLight(); //呼叫自定義 高亮外掛
});

這裡只能 直接呼叫,不能鏈式呼叫。我們知道jQuey是可以鏈式呼叫的,就是可以在一個jQuery物件上呼叫多個方法,如:
$('#id').css({marginTop:'100px'}).addAttr("title","測試“); 
但是我們上面的外掛,就不能這樣鏈式呼叫了。比如:$("p").highLight().css({marginTop:'100px'}); //將會報找不到css方法,原因在與我的自定義外掛在完成功能後,沒有將 jQuery物件給返回出來。接下來,return jQuery物件,讓我們的外掛也支援鏈式呼叫。(其實很簡單,就是執行完我們外掛程式碼的時候將jQuery對像return 出來,和上面的程式碼沒啥區別)

 View Code

4.暴露公共方法 給別人來擴充套件你的外掛(如果有需求的話)
比如的高亮外掛有一個format方法來格式話高亮文字,則我們可將它寫成公共的,暴露給外掛使用者,不同的使用著根據自己的需求來重寫該format方法,從而是高亮文字可以呈現不同的格式。

    //公共的格式化 方法. 預設是加粗,使用者可以通過覆蓋該方法達到不同的格式化效果。
    $.fn.highLight.format = function (str) {
        return "<strong>" + str + "</strong>"; 
    }

5.外掛私有方法
 有些時候,我們的外掛需要一些私有方法,不能被外界訪問。例如 我們外掛裡面需要有個方法 來檢測使用者呼叫外掛時傳入的引數是否符合規範。
6.其他的一些設定,如:為你的外掛加入元資料外掛的支援將使其變得更強大。

完整的高亮外掛程式碼如下:

複製程式碼
//閉包限定名稱空間
(function ($) {
    $.fn.extend({
        "highLight": function (options) {
            //檢測使用者傳進來的引數是否合法
            if (!isValid(options))
                return this;
            var opts = $.extend({}, defaluts, options); //使用jQuery.extend 覆蓋外掛預設引數
            return this.each(function () {  //這裡的this 就是 jQuery物件。這裡return 為了支援鏈式呼叫
                //遍歷所有的要高亮的dom,當呼叫 highLight()外掛的是一個集合的時候。
                var $this = $(this); //獲取當前dom 的 jQuery物件,這裡的this是當前迴圈的dom
                //根據引數來設定 dom的樣式
                $this.css({
                    backgroundColor: opts.background,
                    color: opts.foreground
                });
                //格式化高亮文字
                var markup = $this.html();
                markup = $.fn.highLight.format(markup);
                $this.html(markup);
            });

        }
    });
    //預設引數
    var defaluts = {
        foreground: 'red',
        background: 'yellow'
    };
    //公共的格式化 方法. 預設是加粗,使用者可以通過覆蓋該方法達到不同的格式化效果。
    $.fn.highLight.format = function (str) {
        return "<strong>" + str + "</strong>";
    }
    //私有方法,檢測引數是否合法
    function isValid(options) {
        return !options || (options && typeof options === "object") ? true : false;
    }
})(window.jQuery);
複製程式碼

呼叫

複製程式碼
        //呼叫
        //呼叫者覆蓋 外掛暴露的共公方法
        $.fn.highLight.format = function (txt) {
            return "<em>" + txt + "</em>"
        }
        $(function () {
            $("p").highLight({ foreground: 'orange', background: '#ccc' }); //呼叫自定義 高亮外掛
        });
複製程式碼

 如發現文中內容有誤歡迎交流指出!