編寫插件的目的是給已經有的一系列方法或函數作一個封裝,以便在其餘地方重複使用,提升開發效率和方便後期維護。本文將詳細介紹如何編寫jQuery插件css
jQuery的插件主要分爲3種類型html
一、封裝對象方法jquery
這種插件是將對象方法封裝起來,用於對經過選擇器獲取的jQuery對象進行操做,是最多見的一種插件。此類插件能夠發揮出jQuery選擇器的強大優點,有至關一部分的jQuery的方法,都是在jQuery腳本庫內部經過這種形式「插」在內核上的,例如:parent()方法、appendTo()方法等。這些方法在如今來看都是jQuery自己自帶的方法了。平時,咱們是能夠直接拿來就用的,只需引入jQuery庫就行ajax
二、封裝全局函數正則表達式
能夠將獨立的函數加到jQuery命名空間下,如經常使用的jQuery.ajax()、去首尾空格的jQuery.trim()方法等,都是jQuery內部做爲全局函數的插件附加到內核上去的數組
三、選擇器插件閉包
雖然jQuery的選擇器十分強大,可是在少數狀況下,仍是會須要用到選擇器插件來擴充一些本身喜歡的選擇器app
一、jQuery插件的文件名推薦命名爲jQuery.[插件名].js,以避免和其餘JS庫插件混淆函數
二、全部的對象方法都應當附加到jQuery.fn對象上,而全部的全局函數都應當附加到jQuery對象自己上測試
三、在插件內部的this指向的是當前經過選擇器獲取的jQuery對象,而不像通常方法那樣,如click,內部的this指向的是DOM元素
四、能夠經過this.each來遍歷全部的元素
五、全部的方法或函數插件,都應當以分號結尾。不然壓縮的時候可能出現問題。爲了穩妥些,甚至能夠在插件頭部先加上一個分號,以避免他人不規範的代碼影響自身的插件代碼
六、插件應該返回一個jQuery對象,以保證插件的可鏈式操做
七、避免在插件內部使用$做爲jQuery對象的別名,而應使用完整的jQuery來表示,避免衝突。固然,也能夠利用閉包來回避這種問題,使插件內部繼續使用$做爲jQuery的別名
利用閉包的特性,便可以免內部臨時變量影響全局空間,又能夠在插件內容繼續使用$做爲jQuery的別名。常見的jQuery插件都是如下這種形式的:
(function(){ /*這裏放置代碼*/ })();
首先定義一個匿名函數function(){/*這裏放置代碼*/},而後用括號括起來,變成(function(){/*這裏放置代碼*/})這種形式,最後經過()這個運算符來執行。能夠傳遞參數進行,以供內部函數使用
//爲了更好的兼容性,開始前有個分號 ;(function($){ //此處將$做爲匿名函數的形參 /*這裏放置代碼,可使用$做爲jQuery的縮寫別名*/ })(jQuery); //這裏就將jQuery做爲實參傳遞給匿名函數了
上面的代碼是一種常見的jQuery插件的結構
jQuery提供了兩個用於拓展jQuery功能的方法,即jQuery.fn.extend()方法和jQuery.extend()方法。jQuery.fn.extend()方法用於拓展封裝對象方法的插件,jQuery.extend()方法用於拓展封裝全局函數的插件和選擇器插件。這兩個方法都接受一個參數,類型爲Object。Object對象的"名/值對"分別表明"函數或方法名/函數主體"
【jQuery.fn.extend()】
jQuery.fn.extend()方法用於將一個對象的內容合併到jQuery的原型,以提供新的jQuery實例方法
<label><input type="checkbox" name="foo"> Foo</label> <label><input type="checkbox" name="bar"> Bar</label> <button id="btn1">全選</button> <button id="btn2">全不選</button> <script> jQuery.fn.extend({ check: function() { return this.each(function() { this.checked = true; }); }, uncheck: function() { return this.each(function() { this.checked = false; }); } }); $('#btn1').click(function(){ $( "input[type='checkbox']" ).check(); }); $('#btn2').click(function(){ $( "input[type='checkbox']" ).uncheck(); }); </script>
【jQuery.extend()】
jQuery.extend()方法用一個或多個其餘對象來擴展一個對象,而後返回被擴展的對象
jQuery.extend( target [, object1 ] [, objectN ] )
例如,合併settings對象和options對象,修改並返回settings對象
var settings = {validate:false,limit:5,name:"foo"}; var options = {validate:true,name:"bar"}; var newOptions = jQuery.extend(settings,options); console.log(newOptions);//Object {validate: true, limit: 5, name: "bar"}
jQuery.extend()方法常常被用於設置插件方法的一系列默認參數
function foo(options){ options=jQuery.extend({ name:"bar", length:5, dataType:"xml" },options); }
若是用戶調用foo()方法的時候,在傳遞的參數options對象設置了相應的值,那麼就使用設置的值,不然使用默認值
經過使用jQuery.extend()方法,能夠很方便地用傳入的參數來覆蓋默認值。此時,對方法的調用依舊保持一致,只不過要傳入的是一個映射而不是一個參數列表。這種機制比傳統的每一個參數都去檢測的方式不只靈活並且更加簡潔。此外使用命名參數意味着再添加新選項也不會影響過去編寫的代碼,從而使開發者使用起來更加直觀明瞭
一、封裝jQuery對象方法的插件
編寫設置和獲取顏色的插件color(),該插件用於實現如下兩個功能:
(1)設置匹配元素的顏色
(2)獲取匹配的元素(元素集合中的第一個)的顏色
因爲是對jQuery對象的方法拓展,所以採用拓展第一類插件的方法jQuery.fn.extend()來編寫,這裏給這個方法提供了一個參數value,若是調用方法的時候傳遞了value這個參數,那麼就是用這個值來設置字體顏色,不然就是獲取匹配元素的字體顏色的值
;(function(){ jQuery.fn.extend({ "color":function(value){ if(value == undefined){ return this.css("color"); }else{ return this.css("color",value); } } }); })(jQuery);
實際上,CSS()方法內容已經有判斷value是否爲undefined的機制,因此才能夠根據傳遞參數的不一樣而返回不一樣的值。所以,代碼能夠刪減以下
;(function(){ jQuery.fn.extend({ "color":function(value){ return this.css("color",value); } }); })(jQuery);
<span id="test">測試文字</span> <input type="color" id="color"> <script> ;(function($){ $.fn.extend({ "color":function(value){ return this.css("color",value); } }); })(jQuery); $('#color').on('change',function(){ $('#test').color($(this).val()); }) </script>
另外,若是要定義一組插件,可使用以下所示寫法:
;(function(){ jQuery.fn.extend({ "color":function(value){ //插件代碼 }, "border":function(value){ //插件代碼 }, "background":function(value){ //插件代碼 } }); })(jQuery);
二、封裝全局函數的插件
這類插件是在jQuery命名空間內部添加一個函數
例如新增兩個函數,用於去除左側和右側空格。雖然jQuery已經提供了jQuery.trim()方法來去除兩端空格,但在某些狀況下,會只但願去除某一側的空格
去除左側、右側的空格的函數分別寫成以下jQuery代碼。(text||"")部分是用於防止傳遞進來的text這個字符串變量處於未定義的特殊狀態,若是text是undeined,則返回字符串"",不然返回字符串text。這個處理是爲了保證接下來的字符串替換方法replace()方法不會出錯
;(function($){ $.extend({ ltrim:function( text ){ return (text || "").replace(/^\s+/g,""); }, rtrim:function( text ){ return (text || "").replace(/\s+$/g,""); } }); })(jQuery); var $str = " test "; console.log($.trim($str));//'test' console.log($.ltrim($str));//'test ' console.log($.rtrim($str));//' test'
三、自定義選擇器
jQuery以其強大的選擇器著稱,那麼jQuery的選擇器的工做原理是什麼呢?
jQuery的選擇解析器首先會使用一組正則表達式來解析選擇器,而後針對解析出的每個選擇符執行一個函數,稱爲選擇函數。最後根據這個選擇函數的返回值爲true仍是false來決定是否保留這個元素,這樣就能夠找到匹配的元素節點
如$("div:gl(1)"),該選擇器首先會獲取全部的<div>元素,而後隱式地遍歷這些<div>元素,並逐個將這些<div>元素做爲參數,連同括號裏的「1」等一些參數一塊兒傳遞給gt對應的選擇器函數進行判斷。若是返回true則保留,不然不保留,這樣獲得的結果就是一個符合要求的<div>元素的集合
選擇器的函數一共接受3個參數,形式以下:
function (a,i,m){ //... }
第一個參數爲a,指的是當前遍歷到的DOM元素
第二個參數爲i,指的是當前遍歷到的DOM元素的索引值,從0開始
第三個參數是m,它是由jQuery正則解析引擎進一步解析後的產物,是一個數組:其中最重要的一個是m[3],在$("div:gl(1)")中即爲括號裏的數字「1」。
在jQuery中已經有lt、gt和eq選擇器,所以這裏寫一個介於二者之間(between)的選擇器
思路:在上面的三個參數中,m[3]爲"a,b"的形式,所以把m[3]用","分隔,而後跟索引值i進行對比,若是i在m[3]表示的範圍之間就返回true,不然爲false
;(function($){ $.extend($.expr[":"],{ between:function(a,i,m){ var temp=m[3].split(","); return +temp[0]<i&&i<+temp[1]; } }); })(jQuery);
[注意]經測試,函數中第二個參數i的值始終爲0,沒法獲取索引值,這時就須要自造索引,代碼以下
;(function($){ var $index = -1; $.extend($.expr[":"],{ between:function(a,i,m){ var temp=m[3].split(","); $index++; return +temp[0]<$index&&$index<+temp[1]; } }); })(jQuery);
<div> <i>0</i> <i>1</i> <i>2</i> <i>3</i> <i>4</i> <i>5</i> </div> <button id="btn">測試</button> <script> ;(function($){ var $index = -1; $.extend($.expr[":"],{ between:function(a,i,m){ var temp=m[3].split(","); $index++; return +temp[0]<$index&&$index<+temp[1]; } }); })(jQuery); $('#btn').click(function(){ $('i:between(1,5)').css('background','lightblue'); }); </script>