Статьи

Анти-паттерны и лучшие практики jQuery

Давным-давно в галактике далеко-далеко JavaScript был ненавистным языком. На самом деле «ненавистный» — это преуменьшение; JavaScript был презираемым языком. В результате разработчики обычно относились к нему как к такому, только опрокидывая свои пальцы в воду JavaScript, когда им нужно было внести свой вклад в свои приложения. Несмотря на то, что в языке JavaScript есть много хорошего, из-за широко распространенного невежества мало кто нашел время для его правильного изучения. Вместо этого, как некоторые из вас помнят, стандартное использование JavaScript требовало значительного количества копирования и вставки.

«Не беспокойтесь о том, что делает код или следует ли он наилучшим методам; просто вставьте его!» — Худший совет когда-либо

Поскольку рост jQuery вызвал интерес к языку JavaScript, большая часть информации в Интернете немного отрывочна.

По иронии судьбы, оказывается, что многое из того, что ненавидело сообщество разработчиков, имело очень мало общего с самим языком JavaScript. Нет, настоящей угрозой под маской была DOM, или «Объектная модель документа», которая, особенно в то время, была ужасно непоследовательной от браузера к браузеру. «Конечно, он может работать в Firefox, но как насчет IE8? Хорошо, он может работать в IE8, но как насчет IE7?» Список продолжался без устали!

К счастью, начиная примерно пять лет назад, сообщество JavaScript увидит невероятные изменения в лучшую сторону, поскольку такие библиотеки, как jQuery, были представлены публике. Эти библиотеки не только предоставили выразительный синтаксис, который особенно привлекателен для веб-дизайнеров, но им также удалось выровнять чувство игры, подправив обходные пути для различных особенностей браузера в его API. $.ajax и позвольте jQuery выполнить сложную часть. Перенесемся в будущее, и сообщество JavaScript стало более динамичным, чем когда-либо, во многом благодаря революции jQuery.

Поскольку рост jQuery вызвал интерес к языку JavaScript, большая часть информации в Интернете немного отрывочна. Это происходит не столько из-за невежества писателей, сколько из-за того, что мы все учились. Для появления лучших практик требуется время.

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


Проблема с такими советами заключается в том, что они доводят идею предварительной оптимизации до крайности.

Подобно Ruby on Rails, многие разработчики впервые познакомились с JavaScript через jQuery. Это приводит к общему циклу: изучайте jQuery, влюбляйтесь, копайтесь в ванильном JavaScript и повышайте уровень.

Хотя в этом цикле нет ничего плохого, он подготовил почву для бесчисленных статей, в которых рекомендовалось не использовать jQuery в различных ситуациях из-за «проблем с производительностью». Было бы $.each прочитать, что лучше использовать vanilla for циклов, а не $.each . Или, в какой-то момент, вы могли прочитать, что лучше всего использовать document.getElementsByClassName вместо движка Sizzle jQuery, потому что он быстрее.

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


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

01
02
03
04
05
06
07
08
09
10
$(‘button.confirm’).on(‘click’, function() {
    // Do it once
    $(‘.modal’).modal();
 
    // And once more
    $(‘.modal’).addClass(‘active’);
 
    // And again for good measure
    $(‘modal’).css(…);
});

Хотя этот код может на первый взгляд казаться безвредным (и, честно говоря, в общей схеме вещей), мы следуем плохой практике создания нескольких экземпляров объекта jQuery. Каждый раз, когда мы ссылаемся на $('.modal') , генерируется новый объект jQuery. Это умный?

Думайте о DOM как о пуле: каждый раз, когда вы вызываете $('.modal') , jQuery погружается в пул и выискивает связанные монеты (или элементы). Когда вы неоднократно запрашиваете DOM для того же самого селектора, вы, по сути, выбрасываете эти монеты обратно в воду, чтобы прыгнуть и найти их снова и снова!

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

1
2
3
4
5
6
$(‘button.confirm’).on(‘click’, function() {
    $(‘.modal’)
        .modal()
        .addClass(‘active’)
        .css(…);
});

В качестве альтернативы используйте «кэширование».

1
2
3
4
5
6
7
8
$(‘button.confirm’).on(‘click’, function() {
    // Do it ONLY once
    var modal = $(‘.modal’);
 
    modal.modal();
    modal.addClass(‘active’);
    modal.css(…);
});

С помощью этой техники jQuery подключается к пулу DOM всего один раз, а не три.


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

Хотя в наши дни это было не так широко распространено, не так давно сеть была засыпана бесчисленными статьями по оптимизации производительности селекторов в jQuery. Например, лучше ли использовать $('div p') или $('div').find('p') ?

Готовы к правде? Это не имеет большого значения. Это, безусловно, хорошая идея — иметь общее представление о том, как движок Sizzle jQuery анализирует ваши запросы селектора справа налево (это означает, что лучше быть более точным в конце вашего селектора, а не в начале). И, конечно, чем конкретнее вы можете быть, тем лучше. Ясно, что $('a.button') лучше по производительности, чем $('.button') , поскольку в первом случае jQuery может ограничить поиск только элементами привязки на странице, а не чем все элементы.

Помимо этого, однако, слишком много внимания уделяется производительности селектора. Если вы сомневаетесь, поверьте в то, что команда jQuery состоит из лучших разработчиков JavaScript в отрасли. Если в библиотеке будет достигнуто повышение производительности, они это обнаружат. И, если не они, один из участников сообщества подаст запрос на удаление.

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


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

1
2
3
4
$(‘a.external’).on(‘click’, function() {
    // this callback function is triggered
    // when .external is clicked
});

Вы, конечно, написали много кода, который выглядит именно так; Я знаю, что у меня есть! При ограниченном использовании функции анонимного обратного вызова служат полезными удобствами. Трубка происходит по линии, когда мы входим … в ад обратного вызова (звук удара молнии)!

Ад обратного вызова — это когда ваш код многократно отступает, когда вы продолжаете вкладывать функции обратного вызова.

Рассмотрим следующий довольно распространенный код ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
$(‘a.data’).on(‘click’, function() {
    var anchor = $(this);
    $(this).fadeOut(400, function() {
        $.ajax({
            // …
            success: function(data) {
                anchor.fadeIn(400, function() {
                    // you’ve just entered callback hell
                });
            }
        });
    });
});

Как правило, чем больше отступ в вашем коде, тем больше вероятность того, что в нем будет запах кода. Или, еще лучше, спросите себя, мой код выглядит как Mighty Ducks Flying V?

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

Не лучше ли разбить этот код на более управляемые и тестируемые части? Конечно. Хотя следующее может быть оптимизировано далее, первым шагом к улучшению этого кода может быть:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
var updatePage = function(el, data) {
    // append fetched data to DOM
};
 
var fetch = function(ajaxOptions) {
    ajaxOptions = ajaxOptions ||
        // url: …
        // dataType: …
        success: updatePage
    };
 
    return $.ajax(ajaxOptions);
};
 
$(‘a.data’).on(‘click’, function() {
    $(this).fadeOut(400, fetch);
});

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

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

В приведенном выше коде функция fetch просто вызывает AJAX-вызов указанного URL-адреса. Функция updatePage принимает некоторые данные и добавляет их в DOM. Теперь, если мы хотим протестировать одну из этих функций, чтобы убедиться, что она работает updatePage образом, например, метод updatePage , мы можем updatePage объект данных и отправить его в функцию. Легко!


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

Как пример, нужен ли сборщик даты для формы? Избавьтесь от лишней работы и воспользуйтесь библиотекой пользовательского интерфейса jQuery, управляемой сообществом и прошедшей высокую проверку.

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

1
2
3
4
5
6
7
8
9
<input id=»myDateInput» type=»text»>
 
<script>
$(«#myDateInput»).datepicker({
   dateFormat: ‘yy-mm-dd’
});
 
// Demo: http://jsbin.com/ayijig/2/
</script>

Или как насчет аккордеона? Конечно, вы могли бы написать эту функциональность самостоятельно, или вместо этого, снова воспользоваться преимуществами пользовательского интерфейса jQuery.

Просто создайте необходимую разметку для вашего проекта.

01
02
03
04
05
06
07
08
09
10
11
12
13
<div id=»accordion»>
    <h3><a href=»#»>Chapter 1</a></h3>
    <div><p>Some text.</p></div>
 
    <h3><a href=»#»>Chapter 2</a></h3>
    <div><p>Some text.</p></div>
 
    <h3><a href=»#»>Chapter 3</a></h3>
    <div><p>Some text.</p></div>
 
    <h3><a href=»#»>Section 4</a></h3>
    <div><p>Some text.</p></div>
</div>

Затем, автоматически превратить его в гармошку.

1
2
3
$(function() {
    $(«#accordion»).accordion();
});

Что если бы вы могли создавать вкладки за тридцать секунд?

Создайте разметку:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
<div id=»tabs»>
    <ul>
        <li><a href=»#tabs-1″>About Us</a></li>
        <li><a href=»#tabs-2″>Our Mission</a></li>
        <li><a href=»#tabs-3″>Get in Touch</a></li>
    </ul>
    <div id=»tabs-1″>
        <p>About us text.</p>
    </div>
    <div id=»tabs-2″>
        <p>Our mission text.</p>
    </div>
    <div id=»tabs-3″>
        <p>Get in touch text.</p>
    </div>
</div>

И активировать плагин.

1
2
3
$(function() {
    $(«#tabs»).tabs();
});

Выполнено! Это даже не требует какого-либо заметного понимания JavaScript.


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

Мы будем использовать относительно простой плагин MessageBox в качестве демонстрации для нашего обучения. Не стесняйтесь работать вместе; на самом деле, пожалуйста, сделайте!

Задание: реализовать необходимые функции для отображения диалоговых окон, используя синтаксис $.message('SAY TO THE USER') . Таким образом, например, перед окончательным удалением записи мы можем попросить пользователя подтвердить действие, а не прибегать к негибким и ужасным окнам alert .


Первый шаг — выяснить, как «активировать» $.message . Вместо того, чтобы расширять прототип jQuery, для требований этого плагина нам нужно только присоединить метод к пространству имен jQuery.

1
2
3
4
5
(function($) {
    $.message = function(text) {
    console.log(text);
  };
})(jQuery);

Это так просто; давай, попробуй! Когда вы вызываете $.message('Here is my message') , эта строка должна быть зарегистрирована в консоли браузера (Shift + Command + i, в Google Chrome).


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

Например, при использовании набора тестов jQuery QUnit мы могли бы протестировать код из шага 1, написав:

1
2
3
4
5
module(‘jQuery.message’, {
   test(‘is available on the jQuery namespace’, 1, function() {
       ok($.message, ‘message method should exist’);
   });
});

Функция ok , доступная через QUnit, просто утверждает, что первый аргумент является истинным значением. Если метод message не существует в пространстве имен jQuery, то будет возвращено значение false , и в этом случае тест не пройден.

Следуя шаблону разработки, основанному на тестировании, этот код станет первым шагом. Как только вы заметили, что тест не пройден, следующим шагом будет добавление метода message , соответственно.

Хотя для краткости эта статья не углубится в процесс разработки на JavaScript под управлением тестов, вам рекомендуется обратиться к репозиторию GitHub для этого проекта, чтобы просмотреть все тесты для плагина: https: // github .com / JeffreyWay / MessageBox / блоб / ведущий / тест / MessageBox_test.js


Метод message , который ничего не делает, никому не поможет! Давайте возьмем предоставленное сообщение и покажем его пользователю. Однако вместо того, чтобы встраивать огромный кусок кода в метод $.message , мы вместо этого просто будем использовать функцию для создания экземпляра и инициализации объекта Message .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
(function($) {
    «use strict»;
 
    var Message = {
        initialize: function(text) {
            this.text = text;
 
            return this;
        }
    };
 
    $.message = function(text) {
        // Needs polyfill for IE8—
        return Object.create(Message).initialize(text);
    };
})(jQuery);

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


Если Message представляет одно окно сообщения, каким будет HTML для одного? Давайте создадим div с классом message-box и сделаем его доступным для экземпляра Message через свойство el .

01
02
03
04
05
06
07
08
09
10
11
var Message = {
    initialize: function(text) {
        this.el = $(‘<div>’, {
            ‘class’: ‘message-box’,
            ‘style’: ‘display: none’
        });
        this.text = text;
 
        return this;
    }
};

Теперь у объекта есть непосредственная ссылка на div обтекания для окна сообщения. Чтобы получить к нему доступ, мы могли бы сделать:

1
2
3
4
var msg = Object.create(Message).initialize();
 
// [<div class=​»message-box» style=​»display:​ none»>​</div>​]
console.log(msg.el);

Помните, у нас теперь есть фрагмент HTML, но он еще не был вставлен в DOM. Это означает, что нам не нужно беспокоиться о ненужных перекомпоновках при добавлении контента в div .


Следующий шаг — взять предоставленную строку сообщения и вставить ее в div . Это легко!

1
2
3
4
5
6
initialize: function(text) {
    // …
    this.el.html(this.text);
}
 
// [<div class=​»message-box» style=​»display:​ none»>​Here is an important message​</div>​]

Однако вряд ли мы захотим вставить текст прямо в div . Более реалистично, окно сообщения будет иметь шаблон. Хотя мы могли бы позволить пользователю плагина создать шаблон и ссылаться на него, давайте сделаем все просто и ограничим шаблон объектом Message .

01
02
03
04
05
06
07
08
09
10
11
var Message = {
   template: function(text, buttons) {
       return [
           ‘<p class=»message-box-text»>’ + text + ‘</p>’,
           ‘<div class=»message-box-buttons»>’,
               buttons,
           ‘</div>’
       ].join(»);
 
   // …
 };

В ситуациях, когда у вас нет выбора, кроме как вложить HTML в ваш JavaScript, популярным подходом является сохранение фрагментов HTML как элементов в массиве, а затем объединение их в одну строку HTML.

В этом фрагменте выше текст сообщения теперь вставляется в абзац с классом message-box-text . Мы также установили место для кнопок, которые мы реализуем в ближайшее время.

Теперь метод initialize может быть обновлен до:

1
2
3
4
initialize: function(text) {
    // …
    this.el.html(this.template(text, buttons));
}

Когда запущено, мы строим структуру для окна сообщения:

1
2
3
4
<div class=»message-box» style=»display: none;»>
    <p class=»message-box-text»>Here is an important message.</p>
    <div class=»message-box-buttons></div>
</div>

Для более сложных проектов рассмотрите возможность использования популярного движка шаблонов Handlebars.


Чтобы окно сообщения было настолько гибким, насколько это возможно, пользователь плагина должен иметь возможность дополнительно указать, помимо прочего, какие кнопки должны быть представлены пользователю — такие как «Хорошо», «Отмена», «Да». , «и т. д. Мы должны иметь возможность добавить следующий код:

1
2
3
$.message(‘Are you sure?’, {
    buttons: [‘Yes’, ‘Cancel’]
});

… и создать окно сообщения с двумя кнопками.

Чтобы реализовать эту функцию, сначала обновите определение $.message .

1
2
3
4
5
6
$.message = function(text, settings) {
    var msg = Object.create(Message);
    msg.initialize(text, settings);
 
    return msg;
};

Теперь объект settings будет передан методу initialize . Давайте обновим это.

1
2
3
4
5
6
7
initialize: function(text, settings) {
    this.el = $(‘<div>’, {‘class’: ‘message-box’, ‘style’: ‘display: none’});
    this.text = text;
    this.settings = settings
 
    this.el.html(this.template(text, buttons));
}

Неплохо, но что, если пользователь плагина не указывает никаких настроек? Всегда учитывайте различные способы использования вашего плагина.


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

01
02
03
04
05
06
07
08
09
10
11
12
$.message = function(text, settings) {
    var msg = Object.create(Message);
    msg.initialize(text, settings);
 
    return msg;
};
 
$.message.defaults = {
    icon: ‘info’,
    buttons: [‘Okay’],
    callback: null
};

При таком подходе, если пользователю плагина нужно изменить значения по умолчанию, ему нужно только обновить $.message.defaults , если это необходимо. Помните: никогда не скрывайте значения по умолчанию от пользователя. Сделайте их доступными «снаружи».

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

jQuery предлагает полезный способ переопределить параметры по умолчанию для плагина (или любого объекта, на самом деле) с помощью его метода extend .

1
2
3
4
initialize: function(text, buttons) {
    // …
    this.settings = $.extend({}, $.message.defaults, settings);
}

С этой модификацией this.settings теперь будет равен новому объекту. Если пользователь плагина указывает какие-либо настройки, он переопределит объект по defaults плагина.


Если мы намереваемся добавить пользовательский значок в окно сообщения, в зависимости от действия, необходимо будет добавить класс CSS к элементу и разрешить пользователю соответственно применять фоновое изображение.

В методе initialize добавьте:

1
this.el.addClass(‘message-box-‘ + this.settings.icon);

Если в объекте settings не указан значок, используется info по умолчанию: .message-box-info . Теперь мы можем предложить различные классы CSS (выходящие за рамки этого руководства), содержащие различные значки для окна сообщения. Вот пара примеров, с чего можно начать.

1
2
3
4
5
6
7
.message-box-info {
    background: url(path/to/info/icon.png) no-repeat;
}
 
.message-box-warning {
    background: url(path/to/warning/icon.png) no-repeat;
}

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


Плагин теперь принимает массив кнопок, которые будут применены к шаблону, но мы еще не написали функциональность, чтобы сделать эту информацию пригодной для использования. Первый шаг — взять массив значений кнопок и преобразовать их в необходимые HTML-входные данные. Создайте новый метод в объекте Message для выполнения этой задачи.

1
createButtons: function(buttons) {}

jQuery.map — это полезный метод, который применяет функцию к каждому элементу в массиве и возвращает новый массив с примененными изменениями. Это идеально подходит для наших нужд. Для каждого элемента в массиве кнопок, такого как ['Yes', 'No'] , мы хотим заменить текст вводом HTML с установленным значением, соответственно.

1
2
3
4
5
createButtons: function(buttons) {
  return $.map(buttons, function(button) {
    return ‘<input type=»submit» value=»‘ + button + ‘»>’;
  }).join(»);
}

Затем обновите метод initialize для вызова этого нового метода.

01
02
03
04
05
06
07
08
09
10
initialize: function(text, settings) {
    this.el = $(‘<div>’, {‘class’: ‘message-box’, ‘style’: ‘display: none’});
    this.text = text;
    this.settings = $.extend({}, $.message.defaults, settings);
 
    var buttons = this.createButtons(this.settings.buttons);
    this.el.html(this.template(text, buttons));
 
    return this;
}

Что хорошего в кнопке, если ничего не происходит, когда пользователь нажимает на нее? Хорошее место для хранения всех прослушивателей событий для представления — это специальный метод events для связанного объекта, например:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
initialize: function() {
    // …
    this.el.html(this.template(text, buttons));
    this.events();
},
 
events: function() {
  var self = this;
 
  this.el.find(‘input’).on(‘click’, function() {
    self.close();
    if ( typeof self.settings.callback === ‘function’ ) {
      self.settings.callback.call(self, $(this).val());
    }
  });
}

Этот код немного сложнее, потому что пользователь плагина должен иметь возможность запускать собственную функцию обратного вызова при нажатии кнопки в окне сообщения. Код просто определяет, была ли зарегистрирована функция callback , и, если это так, запускает ее и отправляет через значение выбранной кнопки. Представьте, что в окне сообщения есть две кнопки: «Принять» и «Отмена». Пользователь плагина должен иметь возможность фиксировать значение нажатой кнопки и реагировать соответствующим образом.

Обратите внимание, где мы называем self.close() ? Этот метод, который еще предстоит создать, отвечает за одну вещь: закрытие и удаление окна сообщения из DOM.

1
2
3
4
5
6
7
8
close: function() {
  this.el.animate({
    top: 0,
    opacity: ‘hide’
  }, 150, function() {
    $(this).remove();
  });
}

Чтобы добавить немного чутья, скрывая окно сообщения, мы в течение 150 миллисекунд исчезаем из окна и переносим его вверх.


Функциональность была реализована! Последний шаг — представить окно сообщения пользователю. Мы добавим последний метод show к объекту Message , который вставит окно сообщения в DOM и разместит его.

1
2
3
4
5
6
show: function() {
  this.el.appendTo(‘body’).animate({
    top: $(window).height() / 2 — this.el.outerHeight() / 2,
    opacity: ‘show’
  }, 300);
}

Требуется только простой расчет, чтобы расположить прямоугольник вертикально в центре окна браузера. С этим на месте плагин готов!

1
2
3
4
5
6
7
$.message = function(text, settings) {
  var msg = Object.create(Message).initialize(text, settings);
 
  msg.show();
 
  return msg;
};

Чтобы использовать новый плагин, просто вызовите $.message() и передайте сообщение и любые применимые настройки, например, так:

1
$.message(‘The row has been updated.’);

Или, чтобы запросить подтверждение для некоторых разрушительных действий:

1
2
3
4
5
6
7
8
9
$.message(‘Do you really want to delete this record?’, {
    buttons: [‘Yes’, ‘Cancel’],
    icon: ‘alert’,
    callback: function(buttonText) {
        if ( buttonText === ‘Yes’ ) {
            // proceed and delete record
        }
    }
});


Чтобы узнать больше о разработке jQuery, рекомендуем ознакомиться с моим курсом на этом сайте «30 дней, чтобы изучить jQuery».

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

В то же время можно достичь того же эффекта, $.message бесчисленные функции обратного вызова в $.message , но это редко является хорошей идеей и даже считается анти-паттерном.

Запомните три ключа к поддерживаемому коду и гибкие плагины и скрипты jQuery:

  1. Могу ли я проверить это? Если нет, выполните рефакторинг и разбейте код на части.
  2. Предлагал ли я возможность переопределить мои настройки по умолчанию?
  3. Я следую плохим практикам или делаю предположения?

Чтобы узнать больше о разработке jQuery, рекомендуем вам ознакомиться с моим курсом по созданию скринкастов на этом сайте «30 дней для изучения jQuery».