javascript 使用类和原型编写 jQuery 插件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7149239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 23:06:32  来源:igfitidea点击:

Writing jQuery Plugins Using Classes and Prototypes

javascriptjqueryplugins

提问by Marvin3

Is it good or bad practise writing plugins this way(using class and prototypes), what are disadvatages of this code?

以这种方式编写插件(使用类和原型)是好是坏,这段代码的缺点是什么?

function PluginName(jqueryObject, options) {

}
PluginName.prototype = {
    publicMethod:function() {
    },
    _privateMethod:function() {
    }
}

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

回答by Spycho

See the jQuery docs on plugin authoringfor best practices:

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

  • Always wrap your plugin in (function( $ ){ // plugin goes here })( jQuery );
  • Don't redundantly wrap the this keyword in the immediate scope of your plugin's function
  • Unless you're returning an intrinsic value from your plugin, always have your plugin's function return the this keyword to maintain chainability.
  • Rather than requiring a lengthy amount of arguments, pass your plugin settings in an object literal that can be extended over the plugin's defaults.
  • Don't clutter the jQuery.fn object with more than one namespace per plugin.
  • Always namespace your methods, events and data.
  • 始终包装您的插件 (function( $ ){ // plugin goes here })( jQuery );
  • 不要在插件函数的直接范围内多余地包装 this 关键字
  • 除非你从你的插件中返回一个内在的值,否则总是让你的插件的函数返回 this 关键字以保持可链接性。
  • 不需要大量的参数,而是将您的插件设置传递到一个可以扩展到插件默认值的对象文字中。
  • 不要将 jQuery.fn 对象与每个插件的多个命名空间混为一谈。
  • 始终命名您的方法、事件和数据。

Example

例子

(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 );

Usage:

用法:

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

Defaults and Options Example

默认值和选项示例

(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 );

Usage:

用法:

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

回答by nwellcome

First, as Spycho said, always wrap your plugin in

首先,正如 Spycho 所说,始终将您的插件包装在

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

to avoid conflict with other libraries that use the dollar sign.

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

Second, if you extend the jQuery.fnobject the selection called with something like $("#myDiv")is passed to the plugin as this. This way you don't have to pass the selection as a parameter to the plugin as you've done.

其次,如果您扩展jQuery.fn对象,则使用类似$("#myDiv")名称调用的选择将作为this. 这样你就不必像你所做的那样将选择作为参数传递给插件。

Third, this you did correctly, they suggest that you pass options to the plugin as an object rather than individual parameters, this is so you can easily have and override defaults:

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

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

Fourth, the way you've created your _privateMethoddoesn't actually make it private, to do so you could follow the pattern jQuery suggests in the plugin authoring guidelines

第四,您创建的方式_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 );

This uses applyand callwhich are fancy built-in methods of functions for setting the scope of function calls, see the MDN referenceto understand what is going on there. This way you actually have control over which methods are public versus private.

这使用applycall哪些是用于设置函数调用范围的精美内置函数方法,请参阅MDN 参考以了解那里发生的事情。通过这种方式,您实际上可以控制哪些方法是公共的还是私有的。

EDIT:Finally, if you want to completely maintain jQuery's fluid interface and have your plugin both accept the selection passed by $()and pass it on, in other words, be chainable, your methods need to return the collection of objects they were given:

编辑:最后,如果您想完全维护 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 );

See this jsFiddlefor the final working example.

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

回答by kolobok

The easiest way to write jQuery plugins (especially if they have some internal state) is to use jQuery UI Widget Factory.

编写 jQuery 插件的最简单方法(尤其是当它们有一些内部状态时)是使用 jQuery UI Widget Factory。

I wouldn't recommend to reinvent the wheel and write lots of boilerplate code by yourself.

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

https://learn.jquery.com/jquery-ui/widget-factory/why-use-the-widget-factory/https://learn.jquery.com/plugins/stateful-plugins-with-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/