2014-02-07 25 views
0

我看了一下這個主題:How to create a jQuery plugin with methods?,雖然有很多關於多功能插件的解決方案,但我很感興趣的是如果可以使用一個對象,這樣就不會有像$("selector").plugin().dostuff()這樣難看的構造,而是可以更像這樣使用它:$("selector").plugin.dostuff(),即'插件'是一個對象,不是函數您可以使用JS對象作爲JQuery插件的接口嗎?

我可以寫這樣的插件:

$.fn.plugin = { 
    dostuff: function() {}, 
    domorestuff: function(){} 
}; 

但隨後的內部函數將不能訪問到調用它擺在首位的jQuery對象,如this返回插件對象。有什麼方法可以構建一個基於JQuery的對象的插件嗎?

回答

1

不,你給的理由:你輸了thisthis在編寫插件時非常重要。要獲得this,您的插件必須是是一個函數。

你基本上有實現方法有三種:

  1. 使用字符串參數,例如:

    $("selector").plugin("dostuff"); 
    

    ...,你分派到插件功能中的處理方法。這是目前最流行的。這是jQuery UI,Bootstrap和其他人使用的方式。下面是完整的例子。

  2. 使用「醜陋的構造」,就像你插入的那樣,你的插件是一個函數,並且它返回一個對象(每次都有一個新對象,以保存this)和你可以調用的函數。

  3. 添加幾個插件的方法來jQuery的,而不是隻有一個,使用某種類型的前綴,所以它最終被$("selector").pluginDoThis();$("selector").pluginDoThat();$("selector").pluginDoTheOther();的關鍵是使用前綴來避免名稱衝突。我很久以前纔看到過這種做法,而且我在一段時間內沒有看到這個插件。不是一個真正流行的選擇。

我剛剛發佈this other answer顯示爲#1的全模式(在他們的情況下,該方法是callThisdestroy),例如:

// Create the plugin 
 
(function ($) { 
 
    var methods = { 
 
     init: function(options) { 
 
      // Determine options 
 
      var opts = $.extend({ 
 
       opacity: 0.5    
 
      }, options); 
 

 
      // Remember them 
 
      this.data("pluginname", opts); 
 

 
      // Initial stuff 
 
      this.css("opacity", opts.opacity); 
 
     }, 
 

 
     callThis: function(opts) { 
 
      // Use 'opts' if relevant 
 
      this.css("display","none"); 
 
     }, 
 

 
     destroy: function(opts) { 
 
      this.removeData("pluginame"); 
 
      this.css("display", "").css("opacity", ""); 
 
     } 
 
    }; 
 

 
    jQuery.fn.pluginname = function (options) { 
 
     var method, args; 
 

 
     // Method? 
 
     if (typeof options === "string") { 
 
      // Yes, grab the name 
 
      method = options; 
 

 
      // And arguments (we copy the arguments, then 
 
      // replace the first with our options) 
 
      args = Array.prototype.slice.call(arguments, 0); 
 

 
      // Get our options from setup call 
 
      args[0] = this.data("pluginname"); 
 
      if (!args[0]) { 
 
       // There was no setup call, do setup with defaults 
 
       methods.init.call(this); 
 
       args[0] = this.data("pluginname"); 
 
      } 
 
     } 
 
     else { 
 
      // Not a method call, use init 
 
      method = "init"; 
 
      args = [options]; 
 
     } 
 

 
     // Do the call 
 
     methods[method].apply(this, args); 
 
    }; 
 
})(jQuery); 
 

 
// Example usage 
 
function doInit() { 
 
    $("#target").pluginname(); 
 
    setTimeout(doCallThis, 700); 
 
} 
 
function doCallThis() { 
 
    $("#target").pluginname("callThis"); 
 
    setTimeout(doDestroy, 700); 
 
} 
 
function doDestroy() { 
 
    $("#target").pluginname("destroy"); 
 
    setTimeout(doInit, 700); 
 
} 
 

 
setTimeout(doInit, 700);
<div id="target">This is the target</div> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

+0

好吧,你已經說服我。但是,你能解釋爲什麼這個''在你的例子中起作用,而不是在我的例子中? – Miguel

+0

@Miguel:因爲JavaScript中的this主要由函數的調用方式來設置:如果通過對象屬性調用函數,則在調用中,this指的是該對象(通常)。所以'foo.bar();'用'this'調用'bar'等於'foo'。 '$(「selector」)。plugin();''''用'this調用'plugin'等於'$(「selector」)'返回的jQuery對象。但''(「selector」)。plugin.method();''''''''this''調用''方法'等於'plugin',而不是jQuery對象;對jQuery對象的引用已經丟失。 –

+0

但在你的情況不'方法[方法] .apply(this,args);'涉及調用對象的方法「方法」?那麼爲什麼'this'沒有設置爲「方法」? – Miguel

相關問題