使用类和原型编写jQuery插件

以这种方式编写插件是好事还是坏事(使用类和原型),这些代码有什么不妥之处?

function PluginName(jqueryObject, options) { } PluginName.prototype = { publicMethod:function() { }, _privateMethod:function() { } } // Initializing var myPluginInstance = new PluginName($(".mySelector"), {myOption:1}); myPluginInstance.publicMethod(); 

有关最佳实践,请参阅有关插件创作的jQuery文档 :

  • 总是包装你的插件(function( $ ){ // plugin goes here })( jQuery );
  • 不要在插件函数的直接范围内冗余地包装this关键字
  • 除非你从插件中返回一个内在值,否则总是让你的插件函数返回this关键字以保持可链接性。
  • 不需要大量的参数,而是将插件设置传递给可以在插件的默认值上扩展的对象文字。
  • 不要使每个插件具有多个命名空间的jQuery.fn对象混乱。
  • 始终命名方法,事件和数据。

 (function( $ ){ var methods = { init : function( options ) { // THIS }, show : function( ) { // IS }, hide : function( ) { // GOOD }, update : function( content ) { // !!! } }; $.fn.tooltip = function( method ) { // Method calling logic 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 ); 

用法:

 $('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 

默认值和选项示例

 (function( $ ){ $.fn.tooltip = function( options ) { var settings = { 'location' : 'top', 'background-color' : 'blue' }; return this.each(function() { // If options exist, lets merge them // with our default settings if ( options ) { $.extend( settings, options ); } // Tooltip plugin code here }); }; })( jQuery ); 

用法:

 $('div').tooltip({ 'location' : 'left' }); 

首先,正如Spycho所说,总是包装你的插件

 (function( $ ){ $.fn.PluginName = function() { // plugin goes here }; })( jQuery ); 

避免与使用美元符号的其他图书馆发生冲突。

其次,如果你扩展jQuery.fn对象,那么用$("#myDiv")类的东西调用的选择就会传递给插件。 这样您就不必像以前那样将选择作为参数传递给插件。

第三,你做得正确,他们建议你把选项作为一个对象而不是单个参数传递给插件,这样你就可以轻松拥有并覆盖默认值:

 (function( $ ){ $.fn.PluginName = function(options) { var settings = { myOption: 1 }; if (options) { $.extend( settings, options ); } // plugin goes here }; })( jQuery ); 

第四,你创建_privateMethod的方式实际上并不是私有的,为此你可以遵循jQuery在插件创作指南中建议的模式

 (function( $ ){ var methods = { publicMethod: function(options) { var settings = { myOption: 1 }; if (options) { $.extend( settings, options ); } }, _privateMethod: function() {} } $.fn.PluginName = function(methodName, options) { // use some logic to control what methods are public if (methodName == "publicMethod") { return publicMethod.apply(this, Array.prototype.slice.call( arguments, 1 )); } }; })( jQuery ); 

这使用applycall这些是用于设置函数调用范围的函数的内置方法,请参阅MDN引用以了解其中的内容。 这样,您实际上可以控制哪些方法是公共方法还是私有方法。

编辑:最后,如果你想完全维护jQuery的流畅接口,并让你的插件接受$()传递的选择并传递它,换句话说,可以链接,你的方法需要返回给定的对象集合:

 (function( $ ){ var methods = { publicMethod: function(options) { var settings = { myOption: 1 }; if (options) { $.extend( settings, options ); } return this.each(function() { this.value = (this.value * 1) + settings.myOption; }); }, _privateMethod: function() {} } $.fn.PluginName = function(methodName, options) { // use some logic to control what methods are public if (methodName == "publicMethod") { return methods.publicMethod.apply(this, Array.prototype.slice.call( arguments, 1 )); } }; })( jQuery ); 

有关最终的工作示例,请参阅此jsFiddle 。

编写jQuery插件的最简单方法(特别是如果它们有一些内部状态)是使用jQuery UI Widget Factory。

我不建议重新发明轮子并自己编写大量的样板代码。

https://learn.jquery.com/jquery-ui/widget-factory/why-use-the-widget-factory/ https://learn.jquery.com/plugins/stateful-plugins-with-widget-factory/