Обмен событиями между отдельными компонентами программы можно построить различными способами. В зависимости от потребностей это можно сделать:
через интерфейс Observable или произвольные DOM-события;
В основе этого подходе лежит то, что одна из компонент обладает информацией о другой. Например, имеет ссылку на экземпляр класса или корневой элемент виджета.
через глобальный объект;
Экземпляры компонент ничего не знают друг о друге. Все события пересылаются через один и тот же объект.
через объекты событий.
В этом случае экземпляры компонент так же ничего не знаю друг о друге. А каждое событие имеет отдельный объект в глобальном пространстве имен.
Интерфейс Observable удобен тем, что события одного экземпляра ни как не пересекаются с событиями другого экземпляра одной и той же компоненты.
$("div.primary div.widget").on("update", function () {
alert("update in primary block");
}
$("div.secondary div.widget").on("update", function () {
alert("update in secondary block");
}
Два экземпляра одного и того же виджета, но расположенных в разных блоках генерируют разные события «update».
Когда экземпляр компоненты, генерирующей события, в приложении один или речь идет об общих для всего приложения событиях, то можно использовать паттерн Topic.
Создается глобальный объект, имеющий методы регистрации функции обратного вызова для события и отмены регистрации, а так же метод вызова зарегистрированных колбеков.
var Topic = (function () {
var topics = {};
return function (name) {
var callbacks, method, topic;
if (!name) {
throw new Error("topic must be specified");
}
topic = topics[name];
if (!topic) {
callbacks = jQuery.Callbacks();
topic = {
publish: callbacks.fire,
subscribe: callbacks.add,
unsubscribe: callbacks.remove
};
topics[name] = topic;
}
return topic;
};
}());
Замыкание содержит в себе список всех зарегистрированных событий. Для каждого из них создается менеджер очереди колбеков jQuery.Callbacks , который регистрирует и вызывает их.
Наружу возвращается объект с методами экземпляра jQuery.Callbacks, но именованными в соответствии с действиями, за которые они отвечают: subscribe, unsubscribe и publish.
Topic("archiveAdd").subscribe(function (id) {
console.log("add file with id = " + id + " to archive");
});
Topic("archiveCreate").subscribe(function () {
console.log("start archiving");
});
И в другой компоненте:
$(root).on("click", "li.file button.add", function () {
Topic("archiveAdd").publish($(this).data("fileId"));
});
$(root).on("click", "button.create", function () {
Topic("archiveCreate").publish();
});
В некоторых случаях может быть полезным для каждого события создать свой отдельный объект и использовать ссылку на него в компонентах
var EventObject = function () {
var callbacks = jQuery.Callbacks();
return {
publish: callbacks.fire,
subscribe: callbacks.add,
unsubscribe: callbacks.remove
};
};
Такая реализация может быть близка сторонникам процедурных языков, но мне кажется чужеродным для функционального стиля JavaScript.