_How to Create a Basic Plugin_, 翻譯自 jQuery 官方網站。javascript
有時,你想要在你的代碼裏面實現一個可複用的功能。
舉個例子,若是你想要在一個 jQuery 對象上調用一個簡單的方法,來對這個對象進行一系列的操做,那麼你應該寫一個 jQuery 插件。css
在開始寫插件以前,咱們必須對 jQuery 的工做方式有些許的認識。來看下面的代碼:html
$( "a" ).css( "color", "red" );
這是一句很是基礎的 jQuery 代碼,可是你知道它背後發生了什麼嗎?當你使用 $
去選擇元素的時候,它就會返回一個 jQuery 對象。這個對象包含可用的全部方法(.css()
, .click()
等)和全部符合你傳入選擇器的元素。java
這個對象從 $.fn
對象繼承全部的方法。 $.fn
對象包括全部 jQuery 對象的方法,也就是說,若是你想添加本身的方法的話,你須要將方法添加到 $.fn
對象上。jquery
※ 譯者注 ※
$.fn == $.prototype // true
app
假設咱們如今要創建一個讓元素裏的文字變綠的插件。
咱們須要作的只是在 $.fn
裏添加一個方法 greenify
。函數
$.fn.greenify = function() { this.css( "color", "green" ); }; $( "a" ).greenify(); // Makes all the links green.
注意到咱們在這段代碼裏面用的是 this
而不是 $(this)
。這是由於在 greenify
函數中,this
指代的是 jQuery 對象,因此可使用 jQuery 的全部方法。網站
jQuery 最大的特色之一就是支持鏈式操做。鏈式操做的實現是靠 jQuery 全部的方法返回 jQuery 對象來實現的(也有一些例外,好比無參數的 .width()
返回的就是寬度)。this
只須要增長一行代碼,咱們就可讓咱們的插件變得能夠鏈式操做:prototype
$.fn.greenify = function() { this.css( "color", "green" ); return this; }; $( "a" ).greenify(); // Makes all the links green.
$
這個變量在不少 JavaScript 庫裏都很受歡迎。若是你一塊兒使用 jQuery 和其餘的庫,你可能就得用 jQuery.noConflict()
來讓 jQuery 返還對 $
變量的控制權了。
然而因爲 $
變量已經不是 jQuery 了,咱們的插件就沒辦法工做了。要讓咱們的插件繼續工做,而且也能夠和其餘的庫一塊兒使用,咱們須要將咱們的代碼放入一個即時執行函數表達式中,而後將jQuery當作參數傳入,命名爲 $
:
(function ( $ ) { $.fn.greenify = function() { this.css( "color", "green" ); return this; }; }( jQuery ));
除了上面提到的兩個功能,即時執行函數增長了一層做用域,讓咱們能夠定義本身的私有變量。例如:
(function ( $ ) { var shade = "#556b2f"; $.fn.greenify = function() { this.css( "color", shade ); return this; }; }( jQuery ));
※ 譯者注 ※
jQuery.noConflict()
的做用是返還$
的控制權。爲何說是返還呢?由於 jQuery 在初始化的時候,會記錄
$
這個變量,而後再將$
綁定爲自身。
因此調用jQuery.noConflict()
,其實是將$
賦值爲以前記錄的舊值。
當編寫插件時,咱們最好只在 $.fn
上綁定一個方法。這不只減小了其餘的插件覆蓋你的插件的概率,也減小了你的插件覆蓋其餘插件的概率。
each()
方法通常來講,使用選擇器選擇的 jQuery 對象都是一個集合。若是你想對這裏的某些元素進行操做(好比獲取屬性,計算位置等),你就須要用到 .each()
方法來進行遍歷。
$.fn.myNewPlugin = function() { return this.each(function() { // Do something to each element here. }); };
※ 譯者注 ※
有讀者可能會問,在以前的代碼中.css()
並無進行遍歷,如何使全部元素裏的問題都變成綠色?
這是由於.css()
方法裏已經作了這個遍歷的工做了。
注意到咱們返回的是 .each()
的結果,而不是 this
。這是由於 .each()
也是可鏈式操做的, 它返回的也是 this
。不過這樣寫更加契合鏈式操做的思想。
當你的插件變得愈來愈複雜的時候,你最好經過接受用戶的配置來讓用戶定製某些功能。
最簡單的方法就是使用一個對象來儲存配置。
(function ( $ ) { $.fn.greenify = function( options ) { // This is the easiest way to have default options. var settings = $.extend({ // These are the defaults. color: "#556b2f", backgroundColor: "white" }, options ); // Greenify the collection based on the settings variable. return this.css({ color: settings.color, backgroundColor: settings.backgroundColor }); }; }( jQuery )); /* Example usage */ $( "div" ).greenify({ color: "orange" });
默認的顏色值 #556b2f
被用戶定義的值 orange
覆蓋。
※ 譯者注 ※
x.extend([deep], target [,obj1][,objN])
.extend()
方法主要是將全部obj
的屬性和方法所有添加到target
上。同名的會覆蓋,而null
和undefined
會被忽略。
當只有一個參數的時候,x
就變成了target
,也就是將這個惟一的參數的全部方法和屬性所有添加到x
中。
x
能夠是:
$
$.fn
$.extend()
和$.fn.extend()
的不一樣也就很是明顯了。
(function( $ ) { $.fn.showLinkLocation = function() { this.filter( "a" ).append(function() { return " (" + this.href + ")"; }); return this; }; }( jQuery ));
HTML 結構:
<!-- Before plugin is called: --> <a href="page.html">Foo</a> <!-- After plugin is called: --> <a href="page.html">Foo (page.html)</a>
※ 譯者注 ※
上面的例子裏,this.filter()
和this.href
的this
是不一樣的。前者是 jQuery 對象,後者是 HTMLElement 對象。var $links = $('a'); $links[0] instanceof HTMLElement; // true $links.slice(0, 1) instanceof jQuery; // true $links.each(function(){ this instanceof HTMLElement; // true });