jQuery 的插件開發模式主要有三種:javascript
這裏咱們選用第二種:css
$.fn.myplugin = functin() { // plugin code }
由於這種方法是加在jQuery對象上,能夠在jQuery選擇器選擇元素後直接調用:html
$('body').myplugin();
若對其餘兩種方法有興趣,請自行查看jQuery 官方文檔。java
改變元素的背景顏色插件:jquery
$.fn.tinyPlugin = function(){ this.css('background-color','#fff'); // 這裏的this是jQuery對象,而不是原生的js對象 }
這樣寫的話,顏色不能使用時定義,修改一下:git
$.fn.tinyPlugin = function(bg){ this.css('background-color',bg); }
以上是一個jQuery插件的基本結構。但編寫更復雜的jQuery插件,藉助面向對象的思想可使插件具備更好的擴展性、可維護性。github
1.建立myplugin構造函數segmentfault
2.定義myplugin的方法api
3.添加到jQuery對象中緩存
首先將代碼放到一個自執行的匿名函數中,防止全局對象污染:
根據上面的步驟,基本結構大體以下:
// 定義構造函數 function myplugin($element,options){ // ... } // 添加方法 myplugin.prototype = { method1: function(){ // ... }, method2: function(){ // ... } }; // 添加到jQuery對象中 $.fn.myplugin = function(options){ new myplugin(this,options); }
後面將在這個結構上進行完善:
放到匿名函數內部的主要做用是隔離做用域,避免變量污染,而自執行能夠返回須要的函數或對象,而不須要每次經過條件判斷爲處理,只須要在首次加載的時候賦值給某個變量。更詳細的信息參見知乎上的 這個問題。
;(function($){ // ... })(jQuery);
留意到上面,函數前還加了分號,這是因爲自執行函數前省略分號的表達式時,某些狀況下會報錯,能夠看 這裏。
在匿名函數裏面還傳入了jQuery對象,這樣作的好處是美圓符號 $
在內部是一個私有變量,僅表明jQuery,能夠防止和其餘使用 $
的庫衝突。
有的自執行函數還將window對象、undefined對象傳入,具體做用能夠看 這裏。
options是提供給使用者定義的參數。一個好的插件,應該提供必要的參數給使用者,而且提供好默認的參數,由於不少狀況下不是每一個參數都須要自定義。以前在項目中寫了一個加載更多 LoadMore
插件,就以這個插件爲例:
function LoadMore($element,options){ this.$element = $element; this._defaults = { loadingSelector: ".zc_loading", //加載中的提示 overSelector: ".zc_loaded", // 加載完畢的加載 } this.options = $.extend({},this._defaults,options||{}); // 合併參數 }
通常插件都會有一個 init()
方法,調用插件時作一些初始化操做:
function myplugin($element,options){ this.init(); } // 添加方法 myplugin.prototype = { init: function(){ // ... } };
爲了防止用戶屢次在同一個元素上調用插件,有必要加一些已初始化的判斷。經過在該元素上用 data()
方法緩存插件的實例對象,每次實例化時判斷該緩存對象便可。
$.fn.myplugin = function(options){ if (!$.data(this, 'myplugin')) { $.data(this, 'myplugin', new myplugin(this, options)); } }
$
選擇器返回的有多是多個元素,所以須要返回的全部元素添加插件,直接使用jQuery自帶的 each()
方法:
$.fn.myplugin = function(options){ this.each(function(){ if (!$.data(this, 'myplugin')) { $.data(this, 'myplugin', new myplugin(this, options)); } }); }
注意這裏的this
是jQuery對象,而不是原生JS對象。因此能夠直接使用this.each()
。
因爲jQuery有個鏈式操做的特性,在每一個方法調用後都會返回該對象,所以只須要 return
該對象便可保持鏈式操做:
$.fn.myplugin = function(options){ return this.each(function(){ // ... }); }
插件不只有可配置的參數,不少時候還須要調用方法。好比說「加載更多」插件,可能須要知道如今加載到第幾頁,或者是否已經所有加載完畢。此時就須要調用方法來得到結果。
在前面咱們知道是在 prototype
定義方法:
LoadMore.prototype = { init: function(){}, // 從新加載 reload: function(){}, // 開始加載 startLoad: function(){}, // 本次加載完成 loadOver: function(){}, // 所有加載完畢 allLoadOver: function(){}, // 插入內容 insert: function(content){} }
方法名能夠經過options參數傳入,只需在內部作字符串判斷:
$.fn.LoadMore = function(options,para){ var instance; instance = $.data(this,'LoadMore'); if(!instance){ instance = new LoadMore(this,options); $.data(this,'LoadMore',instance); } // 若是是字符串則調用方法 if($.type(options) === 'string') { return instance[options](para); } return this; // 保持鏈式 }
所以咱們調用方法能夠像下面這樣:
$('#list').LoadMore('startLoad');
可是,當調用的方法須要傳參怎麼辦?很簡單,那就再加一個參數 para
:
$.fn.LoadMore = function(options,para){ // ... // 若是是字符串則調用方法 if($.type(options) === 'string') { return instance[options](para); } return this; // 保持鏈式 }
調用帶參數的方法:
$('#list').LoadMore('insert','這是待插入的內容');
這裏若是要使用回調函數,和上面也是同樣的道理,只需在內部加個函數判斷。不詳述。如有更多的參數,請使用對象 {}
。
在寫 LoadMore
插件的過程當中,還發現須要使用事件,好比說滾動到某個位置時,執行某些操做。也很簡單,事件咱們能夠直接寫在配置參數 options 中:
this._defaults = { onScroll: null, // scroll中 onScrollBottom: null // scroll到底部 }
而後在內部 init()
函數中調用前判斷:
init: function(){ var that = this, $win = $(window), $doc = $(document); $win.on('scroll',function(){ (typeof that.options['onScroll'] == 'function') && that.options['onScroll'](); if($win.scrollTop() + $win.height() >= $doc.height()-10){ (typeof that.options['onScrollBottom'] == 'function') && that.options['onScrollBottom'](); } }); }
如今流行模塊化開發,AMD是require.js在推廣過程當中的規範化產出,AMD說明見 這裏。
下面的代碼可使你的插件兼容AMD規範,能夠在require.js中直接調用,固然,沒有使用require.js直接 <script>
引入也是能夠的。
// amd support (function(factory){ // amd support if(typeof define === 'function' && define.amd){ define(['jquery'],factory); }else { factory(jQuery); } }(function($){ var exports = {}; // 這裏寫插件代碼 return exports; }));
上面的前一段是判斷是否有define函數,有則調用define方法定義一個模塊,不然直接執行。後一段的 exports
對象是模塊的返回對象,模塊對外的接口。關於AMD規範的具體信息,可參考阮一峯的 這篇文章。
上面所寫的就是寫一個插件的大體流程,因爲能力有限,還有不少要完善的地方。想要了解更多,這裏推薦一篇文章 深刻理解jQuery插件開發。另外,這裏提供一個gitHub上面的某位大神寫的插件 SlipHover供參考。