如何创build一个jQuery插件的方法?

我想写一个jQuery插件,将提供额外的function/方法的对象,调用它。 我在网上阅读的所有教程(浏览过去2个小时)至多包括如何添加选项,但不包括附加function。

这是我正在做的事情:

//通过调用该div的插件,将div格式化为一个消息容器

$("#mydiv").messagePlugin(); $("#mydiv").messagePlugin().saySomething("hello"); 

或类似的规定。 下面是它的归结:我调用插件,然后我调用与该插件相关的函数。 我似乎无法find一个方法来做到这一点,我见过很多插件。

这是我迄今为止的插件:

 jQuery.fn.messagePlugin = function() { return this.each(function(){ alert(this); }); //i tried to do this, but it does not seem to work jQuery.fn.messagePlugin.saySomething = function(message){ $(this).html(message); } }; 

我怎么能做到这样的事情?

谢谢!


更新2013年11月18日:我已经改变了哈里的以下评论和upvotes的正确答案。

根据jQuery插件创作页面( http://docs.jquery.com/Plugins/Authoring ),最好不要混淆jQuery和jQuery.fn命名空间。 他们build议这种方法:

 (function( $ ){ var methods = { init : function(options) { }, show : function( ) { },// IS hide : function( ) { },// GOOD update : function( content ) { }// !!! }; $.fn.tooltip = function(methodOrOptions) { if ( methods[methodOrOptions] ) { return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 )); } else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) { // Default to "init" return methods.init.apply( this, arguments ); } else { $.error( 'Method ' + methodOrOptions + ' does not exist on jQuery.tooltip' ); } }; })( jQuery ); 

基本上你把你的函数存储在一个数组中(作用域到包装函数),如果参数是一个string,则返回一个默认方法(这里是“init”),如果参数是一个对象(或null)则检查一个条目。

那么你可以调用像这样的方法…

 $('div').tooltip(); // calls the init method $('div').tooltip({ // calls the init method foo : 'bar' }); $('div').tooltip('hide'); // calls the hide method $('div').tooltip('update', 'This is the new tooltip content!'); // calls the update method 

Javascript的“参数”variables是所有传递参数的数组,因此它可以使用任意长度的函数参数。

以下是我用于使用其他方法创build插件的模式。 你会像这样使用它:

 $('selector').myplugin( { key: 'value' } ); 

或者,直接调用一个方法,

 $('selector').myplugin( 'mymethod1', 'argument' ); 

例:

 ;(function($) { $.fn.extend({ myplugin: function(options,arg) { if (options && typeof(options) == 'object') { options = $.extend( {}, $.myplugin.defaults, options ); } // this creates a plugin for each element in // the selector or runs the function once per // selector. To have it do so for just the // first element (once), return false after // creating the plugin to stop the each iteration this.each(function() { new $.myplugin(this, options, arg ); }); return; } }); $.myplugin = function( elem, options, arg ) { if (options && typeof(options) == 'string') { if (options == 'mymethod1') { myplugin_method1( arg ); } else if (options == 'mymethod2') { myplugin_method2( arg ); } return; } ...normal plugin actions... function myplugin_method1(arg) { ...do method1 with this and arg } function myplugin_method2(arg) { ...do method2 with this and arg } }; $.myplugin.defaults = { ... }; })(jQuery); 

那么这个方法呢?

 jQuery.fn.messagePlugin = function(){ var selectedObjects = this; return { saySomething : function(message){ $(selectedObjects).each(function(){ $(this).html(message); }); return selectedObjects; // Preserve the jQuery chainability }, anotherAction : function(){ //... return selectedObjects; } }; } // Usage: $('p').messagePlugin().saySomething('I am a Paragraph').css('color', 'red'); 

所选对象存储在messagePlugin闭包中,并且该函数返回一个包含与插件关联的函数的对象,在每个函数中,您可以对当前选定的对象执行所需的操作。

你可以在这里testing和使用代码。

编辑:更新代码,以保持jQuery可链接性的力量。

通过引入Widget Factory, jQuery使这一切变得更加简单。

例:

 $.widget( "myNamespace.myPlugin", { options: { // Default options }, _create: function() { // Initialization logic here }, // Create a public method. myPublicMethod: function( argument ) { // ... }, // Create a private method. _myPrivateMethod: function( argument ) { // ... } }); 

初始化:

 $('#my-element').myPlugin(); $('#my-element').myPlugin( {defaultValue:10} ); 

方法调用:

 $('#my-element').myPlugin('myPublicMethod', 20); 

(这是如何构buildjQuery UI库。)

目前select的答案的问题是,你实际上并没有为select器中的每个元素创build一个自定义插件的新实例,就像你正在做的那样…实际上只是创build一个实例并传入select器本身作为范围。

查看这个小提琴的更深入的解释。

相反,您需要使用jQuery.each遍历select器,并为select器中的每个元素实例化自定义插件的新实例。

就是这样:

 (function($) { var CustomPlugin = function($el, options) { this._defaults = { randomizer: Math.random() }; this._options = $.extend(true, {}, this._defaults, options); this.options = function(options) { return (options) ? $.extend(true, this._options, options) : this._options; }; this.move = function() { $el.css('margin-left', this._options.randomizer * 100); }; }; $.fn.customPlugin = function(methodOrOptions) { var method = (typeof methodOrOptions === 'string') ? methodOrOptions : undefined; if (method) { var customPlugins = []; function getCustomPlugin() { var $el = $(this); var customPlugin = $el.data('customPlugin'); customPlugins.push(customPlugin); } this.each(getCustomPlugin); var args = (arguments.length > 1) ? Array.prototype.slice.call(arguments, 1) : undefined; var results = []; function applyMethod(index) { var customPlugin = customPlugins[index]; if (!customPlugin) { console.warn('$.customPlugin not instantiated yet'); console.info(this); results.push(undefined); return; } if (typeof customPlugin[method] === 'function') { var result = customPlugin[method].apply(customPlugin, args); results.push(result); } else { console.warn('Method \'' + method + '\' not defined in $.customPlugin'); } } this.each(applyMethod); return (results.length > 1) ? results : results[0]; } else { var options = (typeof methodOrOptions === 'object') ? methodOrOptions : undefined; function init() { var $el = $(this); var customPlugin = new CustomPlugin($el, options); $el.data('customPlugin', customPlugin); } return this.each(init); } }; })(jQuery); 

和一个工作小提琴 。

你会注意到在第一个小提琴中,所有的div都总是向右移动相同数量的像素。 这是因为只有一个选项对象存在于select器中的所有元素。

使用上面所写的技巧,你会注意到在第二个小提琴中,每个div没有alignment,并随机移动(不包括第一个div,因为它的随机发音器总是在第89行设置为1)。 这是因为我们现在正确地为select器中的每个元素实例化一个新的自定义插件实例。 每个元素都有自己的选项对象,并不保存在select器中,而是保存在自定义插件本身的实例中。

这意味着你可以从新的jQueryselect器访问在DOM中的特定元素上实例化的自定义插件的方法,而不是像在第一个小提琴中那样强制caching它们。

例如,这将使用第二个小提琴中的技巧返回所有选项对象的数组。 它会在第一个返回undefined。

 $('div').customPlugin(); $('div').customPlugin('options'); // would return an array of all options objects 

这是你将不得不访问第一个小提琴中的选项对象,只会返回一个单一的对象,而不是他们的数组:

 var divs = $('div').customPlugin(); divs.customPlugin('options'); // would return a single options object $('div').customPlugin('options'); // would return undefined, since it's not a cached selector 

我build议使用上面的技巧,而不是从当前选定的答案。

更简单的方法是使用嵌套函数。 然后你可以用面向对象的方式链接它们。 例:

 jQuery.fn.MyPlugin = function() { var _this = this; var a = 1; jQuery.fn.MyPlugin.DoSomething = function() { var b = a; var c = 2; jQuery.fn.MyPlugin.DoSomething.DoEvenMore = function() { var d = a; var e = c; var f = 3; return _this; }; return _this; }; return this; }; 

以下是如何调用它:

 var pluginContainer = $("#divSomeContainer"); pluginContainer.MyPlugin(); pluginContainer.MyPlugin.DoSomething(); pluginContainer.MyPlugin.DoSomething.DoEvenMore(); 

不过要小心。 在创build之前,您不能调用嵌套函数。 所以你不能这样做:

 var pluginContainer = $("#divSomeContainer"); pluginContainer.MyPlugin(); pluginContainer.MyPlugin.DoSomething.DoEvenMore(); pluginContainer.MyPlugin.DoSomething(); 

DoEvenMore函数甚至不存在,因为DoSomething函数尚未运行,这是创buildDoEvenMore函数所必需的。 对于大多数jQuery插件,你真的只会有一个层次的嵌套function,而不是两个,因为我已经显示在这里。
只要确保在创build嵌套函数时,在父函数的任何其他代码执行之前,在其父函数的开头定义这些函数。

最后,请注意“this”成员存储在名为“_this”的variables中。 对于嵌套函数,如果需要在调用客户端中引用实例,则应该返回“_this”。 你不能只在嵌套函数中返回“this”,因为这会返回对函数的引用而不是jQuery实例。 返回一个jQuery引用允许你在返回时链接内在的jQuery方法。

我从jQuery插件Boilerplate得到它

也在jQuery插件Boilerplate中描述,重新生成

 // jQuery Plugin Boilerplate // A boilerplate for jumpstarting jQuery plugins development // version 1.1, May 14th, 2011 // by Stefan Gabos // remember to change every instance of "pluginName" to the name of your plugin! (function($) { // here we go! $.pluginName = function(element, options) { // plugin's default options // this is private property and is accessible only from inside the plugin var defaults = { foo: 'bar', // if your plugin is event-driven, you may provide callback capabilities // for its events. execute these functions before or after events of your // plugin, so that users may customize those particular events without // changing the plugin's code onFoo: function() {} } // to avoid confusions, use "plugin" to reference the // current instance of the object var plugin = this; // this will hold the merged default, and user-provided options // plugin's properties will be available through this object like: // plugin.settings.propertyName from inside the plugin or // element.data('pluginName').settings.propertyName from outside the plugin, // where "element" is the element the plugin is attached to; plugin.settings = {} var $element = $(element), // reference to the jQuery version of DOM element element = element; // reference to the actual DOM element // the "constructor" method that gets called when the object is created plugin.init = function() { // the plugin's final properties are the merged default and // user-provided options (if any) plugin.settings = $.extend({}, defaults, options); // code goes here } // public methods // these methods can be called like: // plugin.methodName(arg1, arg2, ... argn) from inside the plugin or // element.data('pluginName').publicMethod(arg1, arg2, ... argn) from outside // the plugin, where "element" is the element the plugin is attached to; // a public method. for demonstration purposes only - remove it! plugin.foo_public_method = function() { // code goes here } // private methods // these methods can be called only from inside the plugin like: // methodName(arg1, arg2, ... argn) // a private method. for demonstration purposes only - remove it! var foo_private_method = function() { // code goes here } // fire up the plugin! // call the "constructor" method plugin.init(); } // add the plugin to the jQuery.fn object $.fn.pluginName = function(options) { // iterate through the DOM elements we are attaching the plugin to return this.each(function() { // if plugin has not already been attached to the element if (undefined == $(this).data('pluginName')) { // create a new instance of the plugin // pass the DOM element and the user-provided options as arguments var plugin = new $.pluginName(this, options); // in the jQuery version of the element // store a reference to the plugin object // you can later access the plugin and its methods and properties like // element.data('pluginName').publicMethod(arg1, arg2, ... argn) or // element.data('pluginName').settings.propertyName $(this).data('pluginName', plugin); } }); } })(jQuery); 

太迟了,但也许它可以帮助某人一天。

我处于相同的情况,就像用一些方法创build一个jQuery插件,读完一些文章和一些轮胎之后,我创build了一个jQuery插件样板( https://github.com/acanimal/jQuery-Plugin-Boilerplate )。

另外,我还开发了一个插件来pipe理标签( acanimal/tagger.html ),并写了两篇博客文章逐步解释创build一个jQuery插件( http:// acuriousanimal。 com / blog / 2013/01/15 / things-i-learned-creating-a-jquery-plugin-part-i / )。

怎么使用触发器? 有谁知道使用它们的任何缺点? 好处是所有的内部variables都可以通过触发器来访问,代码非常简单。

见jsfiddle 。

用法示例

 <div id="mydiv">This is the message container...</div> <script> var mp = $("#mydiv").messagePlugin(); // the plugin returns the element it is called on mp.trigger("messagePlugin.saySomething", "hello"); // so defining the mp variable is not needed... $("#mydiv").trigger("messagePlugin.repeatLastMessage"); </script> 

插入

 jQuery.fn.messagePlugin = function() { return this.each(function() { var lastmessage, $this = $(this); $this.on('messagePlugin.saySomething', function(e, message) { lastmessage = message; saySomething(message); }); $this.on('messagePlugin.repeatLastMessage', function(e) { repeatLastMessage(); }); function saySomething(message) { $this.html("<p>" + message + "</p>"); } function repeatLastMessage() { $this.append('<p>Last message was: ' + lastmessage + '</p>'); } }); } 

在这里我想build议使用参数创build简单的插件的步骤。

JS

 (function($) { $.fn.myFirstPlugin = function( options ) { // Default params var params = $.extend({ text : 'Default Title', fontsize : 10, }, options); return $(this).text(params.text); } }(jQuery)); 

在这里,我们添加了名为params默认对象,并使用extendfunction设置选项的默认值。 因此,如果我们传递空白参数,那么它将设置默认值,否则将设置。

HTML

 $('.cls-title').myFirstPlugin({ text : 'Argument Title' }); 

阅读更多: 如何创buildJQuery插件

这是我的这个简单的版本。 与之前发布的类似,您可以这样称呼:

 $('#myDiv').MessagePlugin({ yourSettings: 'here' }) .MessagePlugin('saySomething','Hello World!'); 

– 或直接访问实例@ plugin_MessagePlugin

 $elem = $('#myDiv').MessagePlugin(); var instance = $elem.data('plugin_MessagePlugin'); instance.saySomething('Hello World!'); 

MessagePlugin.js

 ;(function($){ function MessagePlugin(element,settings){ // The Plugin this.$elem = element; this._settings = settings; this.settings = $.extend(this._default,settings); } MessagePlugin.prototype = { // The Plugin prototype _default: { message: 'Generic message' }, initialize: function(){}, saySomething: function(message){ message = message || this._default.message; return this.$elem.html(message); } }; $.fn.MessagePlugin = function(settings){ // The Plugin call var instance = this.data('plugin_MessagePlugin'); // Get instance if(instance===undefined){ // Do instantiate if undefined settings = settings || {}; this.data('plugin_MessagePlugin',new MessagePlugin(this,settings)); return this; } if($.isFunction(MessagePlugin.prototype[settings])){ // Call method if argument is name of method var args = Array.prototype.slice.call(arguments); // Get the arguments as Array args.shift(); // Remove first argument (name of method) return MessagePlugin.prototype[settings].apply(instance, args); // Call the method } // Do error handling return this; } })(jQuery); 

你可以做:

 (function ($) { var YourPlugin = function (element, option) { var defaults = { //default value } this.option = $.extend({}, defaults, option); this.$element = $(element); this.init(); } YourPlugin.prototype = { init: function () { }, show: function() { }, //another functions } $.fn.yourPlugin = function (option) { var arg = arguments, options = typeof option == 'object' && option;; return this.each(function () { var $this = $(this), data = $this.data('yourPlugin'); if (!data) $this.data('yourPlugin', (data = new YourPlugin(this, options))); if (typeof option === 'string') { if (arg.length > 1) { data[option].apply(data, Array.prototype.slice.call(arg, 1)); } else { data[option](); } } }); }; }); 

通过这种方式,你的插件对象作为数据值存储在你的元素中。

  //Initialization without option $('#myId').yourPlugin(); //Initialization with option $('#myId').yourPlugin({ //your option }); //call show method $('#myId').yourPlugin('show'); 

试试这个:

 $.fn.extend({ "calendar":function(){ console.log(this); var methods = { "add":function(){console.log("add"); return this;}, "init":function(){console.log("init"); return this;}, "sample":function(){console.log("sample"); return this;} }; methods.init(); // you can call any method inside return methods; }}); $.fn.calendar() // caller or $.fn.calendar().sample().add().sample() ......; // call methods 

这实际上可以使用defineProperty以“很好”的方式defineProperty 。 “好”的意思是不必使用()来获取插件名称空间,也不必通过string来传递函数名称。

兼容性nit: defineProperty在古代浏览器(如IE8及以下defineProperty不起作用。 警告: $.fn.color.blue.apply(foo, args)将不起作用,您需要使用foo.color.blue.apply(foo, args)

 function $_color(color) { return this.css('color', color); } function $_color_blue() { return this.css('color', 'blue'); } Object.defineProperty($.fn, 'color', { enumerable: true, get: function() { var self = this; var ret = function() { return $_color.apply(self, arguments); } ret.blue = function() { return $_color_blue.apply(self, arguments); } return ret; } }); $('#foo').color('#f00'); $('#bar').color.blue(); 

JSFiddle链接

根据jquery标准,你可以创build插件如下:

 (function($) { //methods starts here.... var methods = { init : function(method,options) { this.loadKeywords.settings = $.extend({}, this.loadKeywords.defaults, options); methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); $loadkeywordbase=$(this); }, show : function() { //your code here................. }, getData : function() { //your code here................. } } // do not put semi colon here otherwise it will not work in ie7 //end of methods //main plugin function starts here... $.fn.loadKeywords = function(options,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 ecw-Keywords'); } }; $.fn.loadKeywords.defaults = { keyName: 'Messages', Options: '1', callback: '', }; $.fn.loadKeywords.settings = {}; //end of plugin keyword function. })(jQuery); 

如何调用这个插件?

 1.$('your element').loadKeywords('show',{'callback':callbackdata,'keyName':'myKey'}); // show() will be called 

参考: 链接

我认为这可能会帮助你…

 (function ( $ ) { $.fn.highlight = function( options ) { // This is the easiest way to have default options. var settings = $.extend({ // These are the defaults. color: "#000", backgroundColor: "yellow" }, options ); // Highlight the collection based on the settings variable. return this.css({ color: settings.color, backgroundColor: settings.backgroundColor }); }; }( jQuery )); 

以下是一个小插件,具有debugging目的的警告方法。 将这段代码保存在jquery.debug.js文件中:JS:

 jQuery.fn.warning = function() { return this.each(function() { alert('Tag Name:"' + $(this).prop("tagName") + '".'); }); }; 

HTML:

 <html> <head> <title>The jQuery Example</title> <script type = "text/javascript" src = "http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script src = "jquery.debug.js" type = "text/javascript"></script> <script type = "text/javascript" language = "javascript"> $(document).ready(function() { $("div").warning(); $("p").warning(); }); </script> </head> <body> <p>This is paragraph</p> <div>This is division</div> </body> </html> 

下面是我如何做到这一点:

 (function ( $ ) { $.fn.gridview = function( options ) { .......... .......... var factory = new htmlFactory(); factory.header(...); ........ }; }( jQuery )); var htmlFactory = function(){ //header this.header = function(object){ console.log(object); } } 

你所做的基本上是通过新的方法来扩展jQuery.fn.messagePlugin对象 。 这是有用的,但不是在你的情况。

你必须要做的就是使用这种技术

 function methodA(args){ this // refers to object... } function saySomething(message){ this.html(message); to first function } jQuery.fn.messagePlugin = function(opts) { if(opts=='methodA') methodA.call(this); if(opts=='saySomething') saySomething.call(this, arguments[0]); // arguments is an array of passed parameters return this.each(function(){ alert(this); }); }; 

但是你可以完成你想要的东西,我的意思是有一个方法来做$(“#mydiv”)messagePlugin()。saySomething(“hello”); 我的朋友,他开始写关于lugins,以及如何扩展他们与你的function链这里是他的博客的链接