編寫一個jQuery插件開始於給jQuery.fn加入新的功能屬性,此處添加的對象屬性的名稱就是你插件的名稱:javascript
jQuery.fn.myPlugin = function(){ //你本身的插件代碼 };
用戶很是喜歡的$符號哪裏去了? 它仍然存在,可是,爲了不和其餘JavaScript庫衝突,咱們最好將jQuery傳遞給一個自我執行的封閉程序,jQuery在此程序中映射爲$符號,這樣能夠避免$號被其餘庫覆寫。css
(function ($) { $.fn.myPlugin = function () { //你本身的插件代碼 }; })(jQuery);
在這個封閉程序中,咱們能夠無限制的使用$符號來表示jQuery函數。java
如今,咱們能夠開始編寫實際的插件代碼。 可是,在這以前,咱們必須得對插件所處的環境有個概念。 在插件的範圍裏, this關鍵字表明瞭這個插件將要執行的jQuery對象, 這裏容易產生一個廣泛的誤區,由於在其餘包含callback的jQuery函數中,this關鍵字表明瞭原生的DOM元素。這經常會致使開發者誤將this關鍵字無謂的包在jQuery中,以下所示。安全
(function ($) { $.fn.myPlugin = function () { //此處沒有必要將this包在$號中如$(this),由於this已是一個jQuery對象。 //$(this)等同於 $($('#element')); this.fadeIn('normal', function () { //此處callback函數中this關鍵字表明一個DOM元素 }); }; })(jQuery); $('#element').myPlugin();
如今,咱們理解了jQuery插件的基礎知識,讓咱們寫一個插件,作一些事情。架構
(function ($) { $.fn.maxHeight = function () { var max = 0; this.each(function () { max = Math.max(max, $(this).height()); }); return max; }; })(jQuery); var tallest = $('div').maxHeight(); //返回高度最大的div元素的高度
這是一個簡單的插件,利用.height()返回頁面中高度最大的div元素的高度。app
不少時候,一個插件的意圖僅僅是以某種方式修改收集的元素,並把它們傳遞給鏈中的下一個方法。 這是jQuery的設計之美,是jQuery如此受歡迎的緣由之一。 所以,要保持一個插件的chainability,你必須確保你的插件返回this關鍵字。ide
(function ($) { $.fn.lockDimensions = function (type) { return this.each(function () { var $this = $(this); if (!type || type == 'width') { $this.width($this.width()); } if (!type || type == 'height') { $this.height($this.height()); } }); }; })(jQuery); $('div').lockDimensions('width').CSS('color', 'red');
因爲插件返回this關鍵字,它保持了chainability,這樣jQuery收集的元素能夠繼續被jQuery方法如.css控制。 所以,若是你的插件不返回固有的價值,你應該老是在其做用範圍內返回this關鍵字。 此外,你可能會推斷出,傳遞給插件的參數將會在插件的做用範圍內被傳遞。 所以,在前面的例子,字符串’width’變成了插件的類型參數。函數
對於比較複雜的和提供了許多選項可定製的的插件,最好有一個當插件被調用的時候能夠被拓展的默認設置(經過使用$.extend)。 所以,相對於調用一個有大量參數的插件,你能夠調用一個對象參數,包含你了你想覆寫的設置。ui
(function ($) { $.fn.tooltip = function (options) { //建立一些默認值,拓展任何被提供的選項 var settings = $.extend({ 'location': 'top', 'background-color': 'blue' }, options); return this.each(function () { // Tooltip插件代碼 }); }; })(jQuery); $('div').tooltip({ 'location': 'left' });
在這個例子中,調用tooltip插件時覆寫了默認設置中的location選項,background-color選項保持默認值,因此最終被調用的設定值爲:this
{
'location': 'left', 'background-color': 'blue' }
這是一個很靈活的方式,提供一個高度可配置的插件,而無需開發人員定義全部可用的選項。
正確命名空間你的插件是插件開發的一個很是重要的一部分。 正確的命名空間,能夠保證你的插件將有一個很是低的機會被其餘插件或同一頁上的其餘代碼覆蓋。 命名空間也使得你的生活做爲一個插件開發人員更容易,由於它能夠幫助你更好地跟蹤你的方法,事件和數據。
在任何狀況下,一個單獨的插件不該該在jQuery.fnjQuery.fn對象裏有多個命名空間。
(function ($) { $.fn.tooltip = function (options) { // this }; $.fn.tooltipShow = function () { // is }; $.fn.tooltipHide = function () { // bad }; $.fn.tooltipUpdate = function (content) { // !!! }; })(jQuery);
這是不被鼓勵的,由於它$.fn使$.fn命名空間混亂。 爲了解決這個問題,你應該收集對象文本中的全部插件的方法,經過傳遞該方法的字符串名稱給插件以調用它們。
(function ($) { var methods = { init: function (options) { // this }, show: function () { // is }, hide: function () { // good }, update: function (content) { // !!! } }; $.fn.tooltip = function (method) { // 方法調用 if (methods[method]) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof method === 'object' || !method) { return methods.init.apply(this, arguments); } else { $.error('Method' + method + 'does not exist on jQuery.tooltip'); } }; })(jQuery); //調用init方法 $('div').tooltip(); //調用init方法 $('div').tooltip({ foo: 'bar' }); // 調用hide方法 $('div').tooltip('hide'); //調用Update方法 $('div').tooltip('update', 'This is the new tooltip content!');
這種類型的插件架構容許您封裝全部的方法在父包中,經過傳遞該方法的字符串名稱和額外的此方法須要的參數來調用它們。 這種方法的封裝和架構類型是jQuery插件社區的標準,它被無數的插件在使用,包括jQueryUI中的插件和widgets。
一個不爲人知bind方法的功能即容許綁定事件命名空間。 若是你的插件綁定一個事件,一個很好的作法是賦予此事件命名空間。 經過這種方式,當你在解除綁定的時候不會干擾其餘可能已經綁定的同一類型事件。 你能夠經過追加命名空間到你須要綁定的的事件經過 <namespace>
。
(function ($) { var methods = { init: function (options) { return this.each(function () { $(window).bind('resize.tooltip', methods.reposition); }); }, destroy: function () { return this.each(function () { $(window).unbind('.tooltip'); }) }, reposition: function () { //... }, show: function () { //... }, hide: function () { //... }, update: function (content) { //... } }; $.fn.tooltip = function (method) { if (methods[method]) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof method === 'object' || !method) { return methods.init.apply(this, arguments); } else { $.error('Method ' + method + ' does not exist on jQuery.tooltip'); } }; })(jQuery); $('#fun').tooltip(); //一段時間以後... ... $('#fun').tooltip('destroy');
在這個例子中,當tooltip經過init方法初始化時,它將reposition方法綁定到resize事件並給reposition非那方法賦予命名空間經過追加.tooltip。 稍後, 當開發人員須要銷燬tooltip的時候,咱們能夠同時解除其中reposition方法和resize事件的綁定,經過傳遞reposition的命名空間給插件。 這使咱們可以安全地解除事件的綁定並不會影響到此插件以外的綁定。
一般在插件開發的時候,你可能須要記錄或者檢查你的插件是否已經被初始化給了一個元素。 使用jQuery的data方法是一個很好的基於元素的記錄變量的途徑。儘管如此,相對於記錄大量的不一樣名字的分離的data, 使用一個單獨的對象保存全部變量,並經過一個單獨的命名空間讀取這個對象不失爲一個更好的方法。
(function ($) { var methods = { init: function (options) { return this.each(function () { var $this = $(this), data = $this.data('tooltip'), tooltip = $('<div />', { text: $this.attr('title') }); // If the plugin hasn't been initialized yet if (!data) { /* Do more setup stuff here */ $(this).data('tooltip', { target: $this, tooltip: tooltip }); } }); }, destroy: function () { return this.each(function () { var $this = $(this), data = $this.data('tooltip'); // Namespacing FTW $(window).unbind('.tooltip'); data.tooltip.remove(); $this.removeData('tooltip'); }) }, reposition: function () { // ... }, show: function () { // ... }, hide: function () { // ... }, update: function (content) { // ... } }; $.fn.tooltip = function (method) { if (methods[method]) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof method === 'object' || !method) { return methods.init.apply(this, arguments); } else { $.error('Method ' + method + ' does not exist on jQuery.tooltip'); } }; })(jQuery);
將數據經過命名空間封裝在一個對象中,能夠更容易的從一個集中的位置讀取全部插件的屬性。
編寫jQuery插件容許你作出庫,將最有用的功能集成到可重用的代碼,能夠節省開發者的時間,使開發更高效。 開發jQuery插件時,要牢記:
(function($) { /* plugin goes here */ })(jQuery);