Теперь пример из реальной жизни.
Важный аспект, который может понадобиться объектам – это умение работать с событиями.
То есть, чтобы объект мог специальным вызовом генерировать «уведомление о событии», а на эти уведомления другие объекты могли
«подписываться», чтобы их получать.
Например, объект «Пользователь» при входе на сайт может генерировать событие "login" , а другие объекты, например «Календарь» может такие уведомления получать и подгружать информацию о пользователе.
Или объект «Меню» может при выборе пункта меню генерировать событие "select" с информацией о выбранном пункте меню, а другие объекты – подписавшись на это событие, будут узнавать об этом.
События – это средство «поделиться информацией» с неопределённым кругом заинтересованных лиц. А там уже кому надо – тот среагирует. Примесь eventMixin , реализующая события:
var eventMixin = {
/**
Подписка на событие
Использование:
menu.on('select', function(item) { ... }
*/
on: function(eventName, handler) {
if (!this._eventHandlers) this._eventHandlers = {}; if (!this._eventHandlers[eventName]) {
this._eventHandlers[eventName] = [];
}
this._eventHandlers[eventName].push(handler);
},
/**
Прекращение подписки
menu.off('select', handler)
*/
off: function(eventName, handler) {
var handlers = this._eventHandlers && this._eventHandlers[eventName]; if (!handlers) return;
for(var i=0; ihandlers.splice(i‐‐, 1);
}
}
},
/**
Генерация события с передачей данных
this.trigger('select', item);
*/
trigger: function(eventName /*, ... */) {
if (!this._eventHandlers || !this._eventHandlers[eventName]) { return; // обработчиков для события нет
}
// вызвать обработчики
var handlers = this._eventHandlers[eventName]; for (var i = 0; i < handlers.length; i++) {
handlers[i].apply(this, [].slice.call(arguments, 1));
}
}
};
Здесь есть три метода:
.on(имя события, функция) – назначает функцию к выполнению при наступлении события с данным именем. Такие функции хранятся в защищённом свойстве объекта _eventHandlers .
.off(имя события, функция) – удаляет функцию из списка предназначенных к выполнению.
.trigger(имя события, аргументы) – генерирует событие, при этом вызываются все назначенные на него функции, и им передаются аргументы.
Использование:
// Класс Menu с примесью eventMixin function Menu() {
// ...
}
for(var key in eventMixin) { Menu.prototype[key] = eventMixin[key];
}
// Генерирует событие select при выборе значения
Menu.prototype.choose = function(value) { this.trigger("select", value);
}
// Создадим меню
var menu = new Menu();
// При наступлении события select вызвать эту функцию menu.on("select", function(value) {
alert("Выбрано значение " + value);
});
// Запускаем выбор (событие select вызовет обработчики) menu.choose("123");
…То есть, смысл событий – обычно в том, что объект, в процессе своей деятельности, внутри себя ( this.trigger ) генерирует уведомления, на которые внешний код через menu.on(...) может быть подписан. И узнавать из них ценную информацию о происходящем, например – что выбран некий пункт меню.
Один раз написав методы on/off/trigger в примеси, мы затем можем использовать их во множестве прототипов.
Итого
Примесь – объект, содержащий методы и свойства для реализации конкретного функционала. Возможны вариации этого приёма проектирования. Например, примесь может предусматривать конструктор, который должен запускаться в конструкторе объекта. Но как правило просто набора методов хватает.
Для добавления примеси в класс – её просто «подмешивают» в прототип.
«Подмешать» можно сколько угодно примесей, но если имена методов в разных примесях совпадают, то возможны конфликты. Их уже разрешать – разработчику. Например, можно заменить конфликтующий метод на свой, который будет решать несколько задач сразу. Конфликты при грамотно оформленных примесях возникают редко.
Do'stlaringiz bilan baham: |