- PVSM.RU - https://www.pvsm.ru -
Основной целью данной статьи является: показать различия между традиционной реализацией jQuery плагина и реализацией с применением событий. В статье будет: о традиционной реализации jQuery плагина, о работе с событиями в jQuery, и попытка заменить методы или callback-функции плагина событиями.
Статья прежде всего рассчитана на новичков, но есть желание услышать профессиональное мнение людей, знакомых с данным вопросом, имеющих более глубокое понимание вещей, описанных в статье.
1. Теория
1.А. Традиционный плагин jQuery
1.Б. Область видимости переменных
1.В. Работа с событиями в jQuery
1.Г. Применение событий в плагинах
1.Д. Недостатки событий
2. Пример простого приложения с дроблением на плагины
3. Заключение, вывод
4. Список литературы
Плагин в jQuery — это обертка над элементом, реализующая некоторый функционал (поведение), которое обычно ограничено элементом на который навешен плагин.
Плагином может быть практически любой элемент или группа элементов на странице: slider изображений, диалоговое окно, кнопка, видоизмененный checkbox, видоизмененный select, динамический список элементов, и так далее.
Создание традиционного jQuery плагина задача достаточно тривиальная. Для этого необходимо добавить в пространство $.fn новый метод.
(function( $ ) {
$.fn.myPlugin = function(options) {
// Переменная options - настройки плагина
// Объект $(this) - доступ к объекту jQuery с выбранным элементом, на который навешен плагин
// Код плагина будет располагаться здесь
};
})( jQuery );
Такая структура отлично подходит для создания простых плагинов, от которых вам не нужно получать данные.
Но часто нам необходимо получить данные или состояние плагина. Хорошим примером является DatePicker.
Мне известно несколько решений для получения данных:
$('input.date').datePicker('getDate');
$('input.date').datePicker('isDisabled')
.$('input.date').datePicker({onChange: onChangeCallback});
$('input.date').datePicker({onDisable: onDisableCallback})
.$('input.date').on('change', onChangeHandler);
$('input.date').on('disable', onDisableHandler)
.
Проблема в реализации методов Р.1.А и Р.1.Б заключается в том, что при следующем вызове $(element).datePicker(...)
повторно выполняется «конструктор» плагина. Конечно это легко отслеживается путем проверки передаваемых параметров: если передан объект (опции) — это инициализация; если передана строка — необходим вызов метода. Как говорится, «баг это или фича» — пока не хватает опыта понять.
Но я столкнулся с проблемой областей видимости переменных.
Пример 5: Демонстрация проблемы областей видимости [1]
(function( $ ) {
// Опции
var options = {
date: '00-00-0000'
},
// Методы
methods = {
getDate: function()
{
return options.date;
}
};
// Плагин
$.fn.myPlugin = function(o)
{
if (typeof o === 'string' && methods[o] !== null) {
return methods[o].apply();
}
options = o || options;
$(this).text(options.date);
};
// Инициализация плагина
$('[data-test]').myPlugin({
date: '10-10-2013'
});
// Получение данных
alert($('[data-test]').myPlugin('getDate'));
})( jQuery );
На данном этапе все просто: создаем плагин, который выводит дату из опций.
Но проблема возникает, когда необходимо поместить на страницу больше одного плагина данного типа.
Пример 6: Больше одного плагина на странице [2]
Как видим из примера 6 — переменная options, которая была вынесена за пределы плагина — перезаписалась данными при инициализации плагина 2.
$(...).trigger(...)
. В конце я приведу пример, который лишен данного недостатка.
При помощи библиотеки jQuery мы можем как создавать «слушателей» для событий $('.link').on('click', onClickHandler)
, так и вызывать (провоцировать) события $('.link').trigger('click')
.
Обратимся к документации, посмотрим параметры обеих функций:
В общих чертах функция on [3] имеет параметры:
Функция trigger [4] имеет параметры:
Пример 7: Демонстрирующий работу событий [5]
$(function() {
$(document).on('myEvent', function(event, p) {
alert('a: ' + p.a + '; b: ' + p.b);
});
$(document).trigger('myEvent', {
a: '1',
b: '2'
});
});
Чтобы избавиться от проблемы с областью видимости переменных (описанной в примере П.6) и проблемой с навешиванием нескольких слушателей (описанной в решении Р.1.Б) я прибегнул к использованию событий и оберток, реализованных в jQuery (1.В).
Пример 7: Реализация событий в плагине [6]
(function( $ ) {
// Объявление плагина
$.fn.datePicker = function(options)
{
var self = $(this),
options = options || {
year: 2012,
month: 1,
day: 1
};
var date = new Date(options.year, options.month, options.day),
d = new Date(options.year, options.month, 1),
table = $('<table />'),
tr = $('<tr>');
tr.appendTo(table);
// Добавляем начало месяца
for (i=0; i < d.getDay(); i++) {
tr.append('<td />');
}
// Добавляем даты
while (d.getMonth() == date.getMonth()) {
if (i % 7 == 0) {
tr = $('<tr />');
tr.appendTo(table);
i = 0;
}
var td = $('<td>' + d.getDate() + '</td>');
td.data('date', d.toString());
tr.append(td);
d.setDate(d.getDate() + 1);
i++;
}
// Добавляем конец месяца
for (i=0; i < 7 - d.getDay(); i++) {
tr.append('<td />');
}
table.appendTo(self);
// При клике на ячейку таблицы генерируем событие 'change' для плагина
table.find('td').on('click', function() {
// Вторым параметром передаем дату
self.trigger('change', $(this).data('date'));
});
return self;
};
// Инициализация плагина
$('[data-datePiceker]').datePicker();
// Навешивание слушателя на событие
$('[data-datePiceker]').on('change', function(event, date) {
alert(date);
});
})( jQuery );
Что мы получили:
Пример 8 Демонстрирующий работу нескольких инициализаций одного плагина П.7 [7]
Конечно данный подход меняет привычный подход к работе с плагином, я имею ввиду отсутствие традиционных методов получения данных, например $(...).datePicker('getDate')
, но тем не менее на данном этапе моего личного развития, как программиста, данный способ решает некоторые мои проблемы. Я лично, считаю данный поход довольно универсальным, и с недостатками пока не сталкивался — если читатель знает о таковых, пожалуйста не молчите, и хочу так же попросить писать как можно доступней и адекватней.
Для тренировки и обкатки событий написал несколько маленьких Ajax-приложений:
На примерах я показал создание jQuery плагина, определил актуальные для меня проблемы передачи данных и получение данных из плагина, показал применение событий и оберток jQuery, и затронул тему создания приложения, активно использующего плагины jQuery и события.
Я не затронул темы всплывания событий по дереву DOM, а так же хотелось уделить больше внимания созданию приложений с использованием событий. Но, если на то будет карма — обязательно напишу продолжение.
Еще раз хочу обратится к людям, которые создают профессиональные клиентские приложения: я люблю критику, и хочу выслушать мнение о данном подходе, да и в общем хотелось бы узнать больше о создании клиентских приложений из первых уст. Поэтому, пишите — буду признателен.
Спасибо за внимание!
Автор: jMas
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/28260
Ссылки в тексте:
[1] Пример 5: Демонстрация проблемы областей видимости: http://jsbin.com/upuyiy/1/edit
[2] Пример 6: Больше одного плагина на странице: http://jsbin.com/upuyiy/2/edit
[3] on: http://api.jquery.com/on/
[4] trigger: http://api.jquery.com/trigger/
[5] Пример 7: Демонстрирующий работу событий: http://jsbin.com/izecug/1/edit
[6] Пример 7: Реализация событий в плагине: http://jsbin.com/eguyif/2/edit
[7] Пример 8 Демонстрирующий работу нескольких инициализаций одного плагина П.7: http://jsbin.com/eguyif/4/edit
[8] jsbin.com/afupej/1/edit: http://jsbin.com/afupej/1/edit
[9] jsbin.com/urihar/16/edit: http://jsbin.com/urihar/16/edit
[10] twitter.github.com/flight/: http://twitter.github.com/flight/
[11] docs.jquery.com/Plugins/Authoring: http://docs.jquery.com/Plugins/Authoring
[12] Источник: http://habrahabr.ru/post/170987/
Нажмите здесь для печати.