標籤:
轉載自:http://www.cnblogs.com/joey0210/p/3408349.html
前言
如今做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‘ }); //調用自訂 高亮外掛程式 });
一步一步寫jQuery外掛程式