Управление jQuery пользовательские события
-
28-09-2019 - |
Вопрос
Я сделал несколько часов дополнительных исследований, но я до сих пор не могу найти хорошего образца к тому, что я бы подумал, является общей проблемой.
Я работаю над приложением .Net MVC2. Наше приложение состоит из главной страницы, то ряд частичных представлений (включенные страницы) каждый из частичных представлений соответствует виджету, состоящей из HTML структура JS-jQuery кишки
Некоторые из наших виджетов имеют богатые взаимодействия друг с другом, так что, конечно, мы используем событие jQuery, связывающее что-то для этого эффекта:
Сводный виджет данных
$(document).bind("DataUpdated", summaryobject.updateTotals());
Виджет манипуляции с данными
$(document).trigger("DataUpdated");
Проблема у нас есть, так как пользователь навигации к частям приложений, эти виджеты (HTML / DOM) удаляются со страницы и заменит новый набор частичных представлений. Когда пользователь навигациирует обратно HTML (визуальное представление), перезагружается вместе с привязкой jQuery, который создает двойное связывание.
Пока мои решения кажутся хромой для меня.
(1) Свяжитесь с объектом DOM, привязка предназначена для:
$("#summaryobject").bind("DataUpdated", summaryobject.updateTotals());
Проблема с этим, в том, что мой запуск виджет должен знать, какого дома для запуска на: $("#summaryobject")
какой вид поражает цель.
(2) Создайте объект EventBus для тракта, который связан с событиями, и только позволяют связаться с событиями один раз. Проблема, которую я имею в том, чтобы хранить / привязывать события, которые я не могу отследить, кто его создал, поэтому я не могу отменить регистрацию, если мне нужно .... возможно, незарегистрированные события не являются необходимыми событиями.
Какие узоры используют другие для управления пользовательскими событиями?
Решение 4
Я закончил делать это сейчас:
Под моим объектом Pageanager я написал этот метод
function PageManager() {
this.eventBusRegistry = [];
///<summary>Registers Event if not already bound</summary>
this.registerForEvent = function (eventName, eventOwner, functionToBind) {
if (this.eventBusRegistry[eventName + eventOwner] == null) {
this.eventBusRegistry[eventName + eventOwner] = "BOUND";
$(document).bind(eventName, functionToBind);
}
}
}
Для моих виджетов класс я сделал это.
///<summary>Widget</summary>
function Widget(inWidgetName) {
//the data you wish to update.
this.data = {};
//name of widget
this.widgetName = inWidgetName;
}
Widget.prototype.registerForEvent = function (eventName, functiontoBind) {
//Session is the instance of PageManager
Session.registerForEvent(eventName, this.widgetName, functiontoBind);
};
Для любого экземпляра виджета, который вы звоните в регистрацию, для привязки событий.
Это далеко от идеального решения. Наш дизайн все еще будет иметь утечки памяти в том, что мы не отмечаем регистрацию наших объектов JS. Тем не менее, наши объекты перезаписываются каждый раз, когда они загружены, настолько хуже, заключается в том, что каждый объект в приложении может быть зарегистрирован один раз, даже если они не используются.
Однако связывание метода для события связывается с объектом документа, который не перезаписывается, ни курс. Так что этот код остановит нас от репословие. У нас все еще есть немного небрежной установки, однако это последствия должны быть минимизированы.
Другие советы
Есть два хороших решения вашей проблемы (что я вижу).
Удалить все ваши
bind
звонки и замените их одним звонкомdelegate
илиlive
и настроить слушатель, который слушает все событий, которые происходят в вашем приложении и направляют их в соответствующие места. (Другими словами, создайте контроллер).Используйте EventBus, который позволяет не отписаться, а также подписано. Самый простой способ, которым я видел, с помощью Eventbus - Питер Михаукс Сохранение скрипта.
/*
Extremely loosely coupled custom events
Source:
http://peter.michaux.ca/articles/anonymous-events-extremely-loose-coupling
*/
EventManager = {};
EventManager.events = {};
EventManager.subscribe = function( event_name, subscriber, method_name ) {
var event = this.events[event_name];
if ( ! event ) {
event = this.events[event_name] = [];
}
event.push( { s: subscriber, m: method_name } );
return this;
};
EventManager.unsubscribe = function( event_name, subscriber ) {
var event = this.events[event_name];
if ( ! event ) {
return;
}
for ( var i = event.length - 1; i >= 0; i-- ) {
if ( event[i].s === subscriber ) {
event.splice( i, 1 );
}
}
return this;
};
EventManager.unsubscribe_all = function( event_name ) {
delete this.events[event_name];
return this;
};
EventManager.fire = function( event_name ) {
var event = this.events[event_name];
if ( ! event ) {
return this;
}
for ( var i = event.length - 1; i >= 0; i-- ) {
subscription = event[i];
subscription.s[subscription.m].apply( subscription.s, arguments );
}
return this;
};
Примером использования этого второго метода будет:
EventManager.subscribe("DataUpdated", summaryobject, "updateTotals");
// ... at some point later on ...
EventManager.fire("DataUpdated");
// Fires `updateTotals` with `this` bound to `summaryobject`
Вы можете попробовать пару вещей, как:
Назначение имен ваших типов событий. Таким образом, не создавая привязку между двумя конкретными экземплярами взгляда, вы можете создать обобщенную связь между типами взглядов. Из вашего примера выше:
Сводный виджет данных A
$(document).bind("DataUpdated.Statistics", summaryobject.updateTotals());
Виджет Manipulation данных A
$(document).trigger("DataUpdated.Statistics");
Проверьте документацию здесь:http://api.jquery.com/bind/
Разгрузка обработчиков событий всякий раз, когда выгружается виджет или группа из них, до загрузки новых DOM / Handlers.
Вы пытались использовать live()
Метод связывания?