2010-10-08 2 views
2

Я провел несколько часов дополнительных исследований, но я все еще не могу найти хороший образец того, что, по моему мнению, является общей проблемой.Manageing jQuery custom events

Я работаю над приложением .Net MVC2. Наше приложение состоит из главной страницы, затем несколько частичных просмотров (включено страницы) каждый из окон открываются частичного вид соответствует виджету, состоящему из HTML структуры и JS-JQuery кишок

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

Сводка данных Widget

$(document).bind("DataUpdated", summaryobject.updateTotals()); 

манипулирования данных Widget

$(document).trigger("DataUpdated"); 

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

До сих пор мои решения казались мне хромыми.

(1) связываются с DOM объект привязки для:

$("#summaryobject").bind("DataUpdated", summaryobject.updateTotals()); 

Проблема с этим состоит в том, что тогда мой запуск виджет должен знать, что DOM ▪ Таблица для запуска на: $("#summaryobject"), какой вид поражения цель.

(2) Создайте объект EventBus для обработки, который связывает события и позволяет событиям связываться только один раз. Проблема, с которой я сталкиваюсь, заключается в сохранении/привязке событий, которые я не могу отслеживать, кто их создал, поэтому я не могу отменить регистрацию, если мне нужно .... возможно, незарегистрированные события не являются необходимыми событиями.

Какие шаблоны используются другими пользователями для управления настраиваемыми событиями?

ответ

0

я в конечном итоге делает это сейчас:

под моим объектом Pagemanager я написал этот метод

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); 
    }; 

Для любого экземпляра виджета вы вызываете registerForEvent для привязки событий.

Это далеко не идеальное решение. Наш дизайн по-прежнему будет иметь утечки памяти, поскольку мы не будем отменить регистрацию наших объектов JS. Однако наши объекты перезаписываются каждый раз, когда они загружаются, так что худший случай заключается в том, что каждый объект в приложении может быть зарегистрирован один раз, даже если они не используются.

Однако привязка метода к событию связывается с объектом документа, который не перезаписывается или не проходит. Таким образом, этот код не остановит нас от восстановления. У нас все еще есть небольшая конфигурация, но ее разветвления следует минимизировать.

1

Есть два хороших решения вашей проблемы (что я вижу).

  1. Удалить все ваши bind вызовов и заменить их одним вызовом delegate или live и настроить слушателя, который прослушивает все событий, которые происходят в вашем приложении и направляет их в соответствующие места. (Другими словами, создайте контроллер).

  2. Используйте EventBus, который позволяет событиям подписываться и подписываться. Самый простой способ, с которым я столкнулся с EventBus, - это Eventing script от Peter Michaux.


/* 
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` 
+0

Значит, это в основном использует только привязку jQuery для вызова диспетчера событий? Сам менеджер событий является более сложной версией встроенного привязки событий jQuery? Я еще не совсем понял способ огня, но я думаю, что знаю, что он делает. –

+0

@Chris - опция # 2 фактически полностью независима от любой библиотеки javascript. Он создает центральный реестр событий и позволяет всем, что знает об этом, добавлять «слушателей» к событиям. Всякий раз, когда вызывается 'fire', он проверяет, содержит ли реестр (' EventManager.events') ключ от ожидаемого имени.Если это так, то выполняется над массивом и вызывает каждую из функций в массиве событий. –

+0

О, я сейчас вижу это более четко. Я действительно не вижу, как это решает проблему двойного связывания. Это просто воссоздает JQuery eventbus. jQuery предоставляет эту же функциональность с помощью bind/unbind. Я также не вижу преимущества живых для пользовательских привязок. Я вижу преимущество, но не тот, кто решает эту проблему. Я думаю, что моя проблема - это действительно общий дизайн работы приложения. Нам нужно быть умнее, как мы загружаем наши объекты JS и выполняем наши привязки. У меня есть временное решение для этого, но нам нужно будет сделать большой рефакторинг, чтобы сделать все правильно. Я подумаю об этом, но –

0

Вы можете попробовать несколько вещей, как:

  1. Пространства имен Ваше мероприятие типы. Таким образом, в то время как не , создавая привязку между двумя конкретными экземплярами вида , вы можете создать обобщенное отношение между типами просмотров. Из вашего примера выше:

    Сводка данных Виджет манипуляция

    $(document).bind("DataUpdated.Statistics", summaryobject.updateTotals()); 
    

    данных виджету

    $(document).trigger("DataUpdated.Statistics"); 
    

    Ознакомьтесь с документацией здесь: http://api.jquery.com/bind/

  2. Разгрузка обработчики событий всякий раз, когда виджет или группа из них разгружается, перед загрузкой новых DOM/обработчиков .

+0

Триггерный виджет по-прежнему должен вызывать «DataUpdated.Statistics», который плотно соединяет их так же, как привязка к конкретному объекту DOM. –

0

Вы пытались использовать метод привязки live()?

+0

Live выглядит довольно круто, однако из моего первоначального взгляда он кажется, что жить отлично подходит для нестандартных событий. Однако мои клиентские события привязаны к объектам JS, которые остаются зарегистрированными. –

+0

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