Статьи

14 причин, по которым никто не использовал ваш плагин jQuery

Так как многие люди разрабатывают плагины jQuery, нередко можно встретить тот, который просто — из-за отсутствия лучших слов — отстой. Там нет примеров или документации, плагин не следует передовым методам и т. Д. Но вы один из счастливчиков: в этой статье будут подробно описаны подводные камни, которых вы должны избегать.

jQuery не новичок для тех из вас, кто часто посещает Nettuts +. Потрясающие 30-дневные уроки Джеффри Уэя jQuery (и различные другие учебные пособия здесь и в других местах) привели нас всех на путь потрясающего соуса от Sizzle. При всей шумихе (и многих скачках в принятии JavaScript разработчиками и поставщиками браузеров) появилось множество плагинов. Отчасти поэтому jQuery стал самой популярной библиотекой JavaScript из всех доступных! Единственная проблема в том, что многие из них не слишком велики.

В этой статье мы сконцентрируемся не столько на JavaScript, сколько на передовых методах доставки плагинов.


Есть несколько шаблонов, более или менее общепринятых как «Правильный путь» для создания плагинов jQuery. Если вы не следуете этим правилам, ваш плагин может … отстой! Рассмотрим один из самых распространенных шаблонов:

01
02
03
04
05
06
07
08
09
10
11
12
13
(function($, window, undefined){
$.fn.myPlugin = function(opts) {
    var defaults = {
        // setting your default values for options
    }
 
  // extend the options from defaults with user’s options
  var options = $.extend(defaults, opts || {});
 
    return this.each(function(){ // jQuery chainability
      // do plugin stuff
    });
})(jQuery, window);

Во-первых, мы создаем самопризывающуюся анонимную функцию, чтобы оградить себя от использования глобальных переменных. Мы передаем $ , window и undefined . Аргументы, с которыми вызывается самопризывающаяся функция: jQuery и window ; для undefined ничего не передается, поэтому, если мы решим использовать ключевое слово undefined в плагине, на самом деле undefined будет неопределенным.

Это защищает от других сценариев, потенциально назначающих вредоносное значение undefined , например, true !

$ передается как jQuery; мы делаем это таким образом, чтобы гарантировать, что вне анонимной функции $ все еще может ссылаться на что-то другое, например, на Prototype.

Передача переменной для глобально доступного объекта window позволяет получить более сжатый код в процессе минимизации (что также следует делать).

Далее мы используем шаблон плагина jQuery, $.fn.PluginName . Это способ регистрации вашего плагина для использования в формате $(selector).method() . Он просто расширяет прототип jQuery вашим новым методом. Если вы хотите вместо этого создать плагин, который определяет функцию для объекта jQuery, добавьте его напрямую, например, так:

1
2
3
$.PluginName = function(options){
    // extend options, do plugin stuff
}

Этот тип плагина не будет цепным, так как функции, которые определены как свойства объекта jQuery, обычно не возвращают объект jQuery. Например, рассмотрим следующий код:

1
2
3
4
5
$.splitInHalf = function(stringToSplit){
    var length = stringToSplit.length;
    var stringArray = stringToSplit.split(stringToSplit[Math.floor(length/2)]);
    return stringArray;
}

Здесь мы возвращаем массив строк. Имеет смысл просто возвращать это как массив, так как это, вероятно, то, что пользователи захотят использовать (и они могут легко обернуть его в объект jQuery, если они захотят). Напротив, рассмотрим следующий надуманный пример:

1
2
3
4
5
6
$.getOddEls = function(jQcollection){ //
    return jQcollection.filter(function(index){
        var i = index+1;
        return (index % 2 != 0);
    });
}

В этом случае пользователь, вероятно, ожидает, что объект jQuery вернется из $.getOddEls ; Итак, мы возвращаем метод filter , который возвращает коллекцию jQuery, определенную переданной функцией. Хорошее практическое правило — заключать возвращаемые элементы в функцию jQuery, особенно если они могут быть связаны цепочкой; если вы возвращаете массивы, строки, числа, функции или другие типы данных, оставьте их развернутыми.


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

Документация — это практика, в которой нет жестких правил; однако общепризнанно, что чем больше (хорошо организованной) документации у вас есть, тем лучше.

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


Самые популярные плагины предлагают полный доступ к переменным (которые большинство плагинов называют объектами «параметров»), которыми пользователь может захотеть управлять. Они также могут предлагать множество различных конфигураций плагина, чтобы его можно было многократно использовать в разных контекстах. Например, давайте рассмотрим простой плагин слайдера. Параметры, которые пользователь может пожелать контролировать, включают скорость, тип и задержку анимации.

Хорошей практикой также является предоставление пользователю доступа к именам классов / ID, которые добавляются к элементам DOM, вставляемым или управляемым плагином. Но помимо этого им также может потребоваться доступ к функции обратного вызова при каждом переходе слайда или, возможно, при переходе слайда обратно в начало (один полный «цикл»).

Ваша задача — продумать все возможные варианты использования и потребности плагина.

Давайте рассмотрим другой пример: плагин, который выполняет вызов API, должен обеспечивать доступ к возвращаемому объекту API. Возьмите следующий пример простого плагина:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
$.fn.getFlickr = function(opts) {
    return this.each(function(){ // jQuery chainability
        var defaults = { // setting your default options
            cb : function(data){},
            flickrUrl : // some default value for an API call
        }
        // extend the options from defaults with user’s options
        var options = $.extend(defaults, opts || {});
 
        // call the async function and then call the callback
        // passing in the api object that was returned
        $.ajax(flickrUrl, function(dataReturned){
            options.cb.call(this, dataReturned);
        });
    });
}

Это позволяет нам делать что-то вроде:

1
$(selector).getFlickr(function(fdata){ // flickr data is in the fdata object });

Другой способ обнародовать это — предложить варианты «крючков». Начиная с jQuery 1.7.1 и выше, мы можем использовать .on(eventName, function(){}) после вызова нашего плагина, чтобы разделить поведение на их собственные функции. Например, с плагином выше, мы могли бы изменить код так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
$.fn.getFlickr = function(opts) {
    return this.each(function(i,el){
        var $this = el;
        var defaults = { // setting your default options
            flickrUrl : «http://someurl.com» // some default value for an API call
        }
        var options = $.extend(defaults, opts || {});
 
        // call the async function and then call the callback
        // passing in the api object that was returned
        $.ajax(flickrUrl, function(dataReturned){
            // do some stuff
            $this.trigger(«callback», dataReturned);
        }).error(function(){
                $this.trigger(«error», dataReturned);
            });
    });
}

Это позволяет нам вызывать плагин getFlickr и getFlickr другие обработчики поведения.

1
$(selector).getFlickr(opts).on(«callback», function(data){ // do stuff }).on(«error», function(){ // handle an error });

Вы можете видеть, что предоставление такого рода гибкости абсолютно важно; чем более сложные действия выполняются вашими плагинами, тем более сложный элемент управления должен быть доступен.


Итак, совет номер три предполагает, что чем сложнее действия ваших плагинов, тем более сложный элемент управления должен быть доступен . Однако большая ошибка — слишком много опций, необходимых для работы плагина. Например, для плагинов на основе пользовательского интерфейса идеально иметь поведение по умолчанию без аргументов.

1
$(selector).myPlugin();

Конечно, иногда это нереально (например, пользователи могут загружать определенный канал). В этом случае вы должны сделать некоторые тяжелые работы для них. Есть несколько способов передачи параметров в плагин. Например, допустим, у нас есть простой плагин Tweet fetcher. Должно быть поведение по умолчанию для этого сборщика твитов с единственной обязательной опцией (имя пользователя, из которого вы хотите извлечь).

1
$(selector).fetchTweets(«jcutrell»);

По умолчанию может, например, захватить один твит, обернуть его в тег абзаца и заполнить элемент селектора этим HTML. Такое поведение большинство разработчиков ожидают и ценят. Гранулярные параметры должны быть именно такими: параметры.


Конечно, в зависимости от типа плагина неизбежно, что вам придется включать CSS-файл, если он сильно основан на манипуляциях с пользовательским интерфейсом. Вообще говоря, это приемлемое решение проблемы; большинство плагинов поставляются в комплекте с изображениями и CSS. Но не забывайте совет номер два — документация должна также включать, как использовать / ссылаться на таблицы стилей и изображения. Разработчики не захотят тратить время на просмотр вашего исходного кода, чтобы разобраться в этом.

Вещи должны просто … работать.

С учетом вышесказанного лучше всего использовать либо внедренные стили (которые легко доступны через параметры плагинов), либо стили, основанные на классах / ID. Эти идентификаторы и классы также должны быть доступны через опции, как упоминалось ранее. Однако встроенные стили переопределяют внешние правила CSS; смешивать их не рекомендуется, так как разработчику может потребоваться много времени, чтобы понять, почему их правила CSS не соблюдаются элементами, созданными вашим плагином. Используйте свое лучшее суждение в этих случаях.

Как правило, встроенный CSS — это плохо, если только он не настолько минимален, что не требует собственной внешней таблицы стилей.


Доказательство в пудинге: если вы не можете предоставить практический пример того, что ваш плагин делает с сопровождающим кодом, люди будут быстро отключены к использованию вашего плагина. Просто как тот. Не ленись.

Хороший шаблон для примеров:

  • Пример «hello world» — обычно вызов плагина с минимальной передачей конфигурации / параметров и сопровождающим html / css
  • Несколько более сложных примеров — обычно с примерами полной функциональности нескольких опций
  • Пример интеграции — если кто-то может использовать другой плагин с вашим плагином, здесь вы можете показать, как это сделать. (Это также дает вам бонусные очки в мире разработки с открытым исходным кодом. Престижность.)

jQuery, как и любая хорошая библиотека кода, растет с каждым выпуском. Большинство методов сохраняются даже после того, как поддержка устарела. Тем не менее, новые методы добавляются; Прекрасным примером этого является метод .on() , который является новым .on() jQuery для делегирования событий. Если вы напишите плагин, который использует .on() , людям, использующим jQuery 1.6 или более раннюю .on() , не повезет. Сейчас я не предлагаю вам код для наименьшего общего знаменателя, но в своей документации обязательно объясните, какую версию jQuery поддерживает ваш плагин. Если вы представите плагин с поддержкой jQuery 1.7, вам следует настоятельно рекомендовать поддерживать поддержку 1.7 даже после выхода версии 1.8. Вам также следует рассмотреть возможность использования новых / лучших / более быстрых функций в jQuery по мере их появления.

Поощряйте разработчиков обновляться, но не ломайте свой плагин слишком часто! Один из вариантов — предложить устаревшие, не поддерживаемые версии вашего плагина.


Пришло время кусать пулю, если вы еще не научились использовать контроль версий.

Наряду с сохранением поддержки / совместимости вашей версии jQuery в вашей документации, вы также должны работать в области контроля версий. Контроль версий (в частности, через GitHub ) в значительной степени является домом социального кодирования. Если вы разрабатываете плагин для jQuery, который хотите в конечном итоге опубликовать в официальном репозитории, он все равно должен храниться в репозитории GitHub; пришло время кусать пулю, если вы не научились использовать контроль версий. Есть множество преимуществ для контроля версий, все из которых выходят за рамки этой статьи. Но одним из основных преимуществ является то, что он позволяет людям просматривать изменения, улучшения и исправления совместимости, которые вы вносите, и когда вы их делаете. Это также открывает поле для вклада и настройки / расширения плагинов, которые вы пишете.


Мир не нуждается в другом плагине слайдера.

Хорошо, мы проигнорировали это достаточно долго: некоторые «плагины» бесполезны или слишком поверхностны, чтобы их можно было назвать плагином. Мир не нуждается в другом плагине слайдера! Следует отметить, однако, что внутренние команды могут разрабатывать свои собственные плагины для своих собственных нужд, что совершенно нормально. Однако, если вы надеетесь внедрить свой плагин в сферу социального кодирования, найдите причину написать больше кода. Как говорится, нет смысла изобретать велосипед. Вместо этого возьмите чужой руль и постройте гоночный автомобиль. Конечно, иногда есть новые и лучшие способы сделать то же самое, что уже было сделано. Например, вы очень хорошо могли бы написать новый плагин слайдера, если вы используете более быструю или новую технологию.


Это довольно просто: предложите минимизированную версию вашего кода. Это делает его меньше и быстрее. Это также гарантирует, что ваш Javascript без ошибок при компиляции. Когда вы минимизируете свой код, не забудьте также предложить несжатую версию, чтобы ваши коллеги могли просмотреть базовый код. Бесплатные и недорогие инструменты существуют для разработчиков на всех уровнях опыта.

Обратитесь к совету номер тринадцать для автоматизированного решения.


Когда вы пишете плагин, он предназначен для использования другими, не так ли? По этой причине наиболее эффективный исходный код хорошо читается. Если вы пишете бесчисленные умные однострочные лямбда-функции или имена ваших переменных не семантические, будет сложно отлаживать ошибки, когда они неизбежно происходят. Вместо того, чтобы писать короткие имена переменных, чтобы сэкономить место, следуйте совету в совете номер девять (минимизируйте!). Это еще одна часть хорошей документации; Приличные разработчики должны иметь возможность просматривать ваш код и понимать, что он делает, не тратя слишком много энергии.

Если вы обнаружите, что называете переменные « a » или « x », вы делаете это неправильно.

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


Как бы нам ни нравилось использовать jQuery, важно понимать, что это библиотека, и это требует небольших затрат. В общем, вам не нужно слишком беспокоиться о таких вещах, как производительность селектора jQuery. Не будь противным, и у тебя все будет хорошо. JQuery высоко оптимизирован. Тем не менее, если единственная причина, по которой вам нужен jQuery (или плагин), состоит в том, чтобы выполнить несколько запросов к DOM, вы можете рассмотреть возможность полного удаления абстракции и вместо этого придерживаться ванильного JavaScript или Zepto.

Примечание: если вы решите придерживаться ванильного JavaScript, убедитесь, что вы используете кросс-браузерные методы. Возможно, вам понадобится небольшой polyfill для новых API.


Используйте Grunt. Период.

Grunt — это «инструмент для построения командной строки на основе задач для проектов JavaScript», который подробно описывался здесь недавно на Nettuts + . Это позволяет вам делать такие вещи:

1
grunt init:jquery

Эта строка (выполняется в командной строке) подскажет вам ряд вопросов, таких как заголовок, описание, версия, репозиторий git, лицензии и так далее. Эти сведения помогают автоматизировать процесс настройки документации, лицензирования и т. Д.

Grunt делает гораздо больше, чем просто создает собственный шаблонный код для вас; он также предлагает встроенные инструменты, такие как code linter JSHint , и может автоматизировать тесты QUnit для вас, если у вас установлен PhantomJS (о котором заботится Grunt). Таким образом, вы можете оптимизировать рабочий процесс, так как тесты запускаются в терминале мгновенно при сохранении.


Да, кстати — вы тестируете свой код, верно? Если нет, как вы можете гарантировать / объявить, что ваш код работает, как ожидалось? Ручное тестирование имеет место, но если вы обновляете браузер бесчисленное количество раз в час, вы делаете это неправильно. Подумайте об использовании таких инструментов, как QUnit , Jasmine или даже Mocha .

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

Если концепция тестирования плагинов jQuery является для вас совершенно новой, рассмотрите нашу эксклюзивную премиальную заставку « Методы тестирования плагинов jQuery» . Кроме того, мы запустили новый курс «JavaScript Testing With Jasmine» позже на этой неделе!


Мы не будем делать вам одолжение, просто говоря вам, что вы делаете неправильно. Вот несколько ссылок, которые помогут вам вернуться на правильный путь!


Если вы пишете плагин jQuery, крайне важно, чтобы вы избегали ловушек, перечисленных выше. Я пропустил какие-либо ключевые признаки плохо выполненного плагина?