Есть ли лучший способ / шаблон для написания этого плагина jQuery? - PullRequest
3 голосов
/ 02 марта 2012

У меня есть поисковый плагин, который довольно сложный: у него разные версии пользовательского интерфейса и функциональности, а также множество взаимозависимых элементов domElements. Несколько экземпляров плагина будут существовать на странице одновременно.

Я использую базовый шаблон разработки jQuery: http://docs.jquery.com/Plugins/Authoring

Чтобы сохранить параметры, взаимозависимые события и все виды поиска в домене для нескольких объектов, я пришел к передаче соответствующего элемента каждой функции и сохранению состояния / параметров / взаимозависимостей в атрибуте данных, который я извлекать каждый раз. Это работает, и предотвращает столкновение событий, но это кажется грязным способом написания кода.

Каков наилучший способ хранения состояния в нескольких экземплярах? То, как я это делаю, является огромным излишним, и я что-то упускаю? Вероятно, это связано с моим неправильным пониманием создания классов, подобных объектам, в шаблоне плагина jQuery.

(function($) {
var _options = {};

var methods = {
    init: function(options) {
        return this.each(function() {
            if (options) {
                _options = $.extend($.fn.examplePlugin.defaults, options);
            } else {
                _options = $.fn.examplePlugin.defaults;
            }
            $this = $(this);
            var data = $this.data('examplePlugin');
            if (!data) {

                $this.data('examplePlugin', {
                    target: $this
                });
                $.each(_options, function(key, value){
                    $this.data('examplePlugin')[key] = value;
                });
                data = $this.data('examplePlugin');
            }
            //Cache dom fragment plugin is in (if passed)
            if (data.domContextSelector == null || data.domContextSelector == "") {
                data.domContext = $(body);
            } else {
                data.domContext = $(data.domContextSelector);
            }
            init($this);
        });
    }
};
var init = function(element) {
    data = getData(element);
    //Storing dom elements to avoid lookups
    data.relatedElement = $(data.relatedElementSelector, data.domContext);
    element.click(function(event){
        doSomethingCool($(event.currentTarget));
    });
};
var doSomethingCool = function(element) {
    data = getData(element);
    element.slideUp();
    data.relatedElement.slideDown();
};
var adjustHeight = function(element) {
    data = getData(element);
    element.height(data.relatedElement.height());
};
var getData = function(element) {
    return $(element).data('examplePlugin');
};

$.fn.examplePlugin = function(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 exist on jQuery.examplePlugin');
    }
    return false;
};
$.fn.examplePlugin.defaults = {
    defaultA: 'something',
    relatedElementSelector: '#related',
    domContextSelector: 'header.header'
};})(jQuery);

Ответы [ 3 ]

2 голосов
/ 02 марта 2012

Да, если вы следуете руководству jQuery, вы создаете его в соответствии с тем, как оно должно быть построено, и используете то, для чего оно предназначено (особенно цепочку).

Однако я неТ обязательно следует по этому пути.Есть много способов сделать эти плагины, например, , например, этот парень , который создал шаблон для плагинов jQuery, которые НЕ основаны на дизайне jQuery, а скорее в перспективе ООП (что я предпочитаю).Я вижу это как чище, но жертвую тем, что не следую обычному синтаксису (element.myPlugin({options}) и неспособности связать (пока вы немного не измените))

У того же парня есть более старый пост, который являетсяшаблон для обычного дизайна плагинов JQuery.

0 голосов
/ 13 января 2013

Лично я предлагаю придерживаться того, что команда jQuery рекомендует , с точки зрения шаблонов проектирования плагинов. Это помогает поддерживать согласованность и делает ваш плагин более дружелюбным к сообществу.

Сказав это ...

Я столкнулся с проблемой попытки сохранить состояние нескольких элементов . Одно решение, которое я нашел, состоит в том, чтобы использовать jQuery Data API (который выглядит следующим образом: $( selector ).data( key, value )) для хранения метаинформации как состояния элемента или состояния приложения.

Хорошая особенность использования data () заключается в том, что он не обновляет / не обрабатывает DOM, а использует внутренние метаданные jQuery, поэтому он быстрее доступен, чем попытка сохранить скрытые поля ввода информации, изменить имена классов или выполнить другие действия. Приколы, которые разработчики пытались использовать для хранения данных на стороне клиента. (Имейте также в виду, что вам не нужно использовать тип документа HTML5 для использования API данных, но если вы сделаете data- *, то ключевые атрибуты будут чрезвычайно полезны !)

Это сложно, когда все элементы имеют свои собственные состояния, но элемент current контролирует общее состояние плагина. Для этого сценария я использую тег body для хранения данных о текущем элементе , примерно так:

    $('body').data('myPluginNameSpace.current', selectorRef );

Таким образом, когда мне нужно проверить состояние моего плагина / страницы / приложения или прослушать событие, специфичное для плагина, которое всплывает до объекта документа, я могу быстро найти текущий / выбранный элемент, и применить к нему любые изменения или поведение пользовательского интерфейса:

    var currentElementRef = $('body').data('myPluginNameSpace.current');
    doFunStuff( currElementRef );

Существует также ряд других способов сделать это, например, создание пользовательского объекта Event и присоединение к нему пользовательских параметров :

    var myPluginEvent = jQuery.Event( 'customEvent.myPluginNameSpace', { myProp : myValue });
    $( document ).trigger( myPluginEvent );

Когда ваше пользовательское событие запускается и позже обрабатывается с помощью функции обратного вызова, ваши пользовательские параметры присоединяются к объекту события, передаваемому обработчику:

   $( document ).on( 'customEvent.myPluginNameSpace', function( e ){
      doStuff( e.myProp ); //you can access your custom properties attach to the event
    });

Вы можете добраться до одного и того же пункта назначения по разным дорогам; это красота и ужас JavaScript.

В вашем конкретном случае имейте в виду, что вам не нужно, чтобы все работало внутри return this.each({ }) части функции method.init для вашего плагина:

Например, если вы не устанавливаете конкретные параметры для каждого элемента, я бы выбрал ту часть, где вы расширяете объект параметров для каждого элемента!

var methods = {
    init: function(options) {
        //DO OPTIONS/EVENTLISTENER/etc STUFF OUT HERE
        return this.each(function() {
            //DONT DO THIS
            if (options) {
                _options = $.extend($.fn.examplePlugin.defaults, options);
            } else {
                _options = $.fn.examplePlugin.defaults;
            }

Попробуйте вместо этого:

...
    var methods = {

        init : function( options ){

          //do setup type stuff for the entire Plugin out here
          var _options = $.MyPlugin.options = $.extend( defaults, options );

          //add some listeners to $(document) that will later be handled               
          //but put them in an external function to keep things organized:
          //methods.addListeners() 

          //this refers to the array of elements returned by $(selector).myPlugin();
          //this.each() iterates over, EACH element, and does everything inside (similar to Array.map())
          //if the selector has 100 elements youre gonna do whats in here 100 times
          return this.each(function(){
            //do function calls for individual elements here        
          });

        },

Кроме того, использование пользовательских событий поможет вам! Добавьте некоторые прослушиватели событий к объекту документа и дайте обработчикам событий выяснить, с каким элементом следует взаимодействовать, используя API данных или пользовательские параметры событий.

0 голосов
/ 02 марта 2012

Я нашел ваш твит, когда проверял, как мой плагин сохраняет состояние, и изучал, как плагин разрабатывался в этом уроке http://tutsplus.com/lesson/head-first-into-plugin-development/

В этом широком уроке мы погрузимся в разработку плагинов jQuery. По пути мы рассмотрим различные лучшие практики и методы для обеспечение высочайшего уровня гибкости для пользователей вашего плагины.

...