Создание плагинов jQuery с использованием классов и прототипов

Это хорошая или плохая практика написания плагинов таким образом (с использованием класса и прототипов), каковы недостатки этого кода?

function PluginName(jqueryObject, options) {

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

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

Ответ 1

Обратитесь к jQuery docs на создание плагинов для лучших практик:

  • Всегда заверните свой плагин в (function( $ ){ // plugin goes here })( jQuery );
  • Не избыточно обертывайте это ключевое слово в непосредственной близости от вашей функции плагина
  • Если вы не возвращаете внутреннее значение из своего плагина, всегда используйте функцию плагина для этого ключевого слова, чтобы поддерживать целостность.
  • Вместо того, чтобы требовать большого количества аргументов, передайте свои настройки плагина в литеральном объекте, который может быть расширен по умолчанию по умолчанию.
  • Не загромождайте объект 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'
});

Ответ 2

Во-первых, как сказал Spycho, всегда добавляйте плагин в

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

чтобы избежать конфликта с другими библиотеками, использующими знак доллара.

Во-вторых, если вы расширяете объект jQuery.fn, выбор, который называется с чем-то вроде $("#myDiv"), передается плагину как this. Таким образом, вам не нужно передавать выбор в качестве параметра в плагин, как вы это сделали.

В-третьих, это вы сделали правильно, они предлагают, чтобы вы передавали параметры плагину как объект, а не отдельные параметры, поэтому вы можете легко и переопределить значения по умолчанию:

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

В этом случае используются apply и call, которые представляют собой причудливые встроенные методы функций для установки диапазона вызовов функций, см. ссылка MDN понять, что там происходит. Таким образом, вы фактически контролируете, какие методы являются общедоступными и частными.

EDIT: Наконец, если вы хотите полностью поддерживать интерфейс среды 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 для окончательного рабочего примера.

Ответ 3

Самый простой способ написать 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/