Управление пользовательскими событиями jQuery - PullRequest
2 голосов
/ 08 октября 2010

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

Я работаю над приложением .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());

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

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

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

Ответы [ 4 ]

1 голос
/ 08 октября 2010

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

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

  2. Используйте EventBus, который позволяет отписываться и подписываться на события.Самый простой способ сделать это с помощью EventBus - это сценарий Питера Мишо Eventing .


/* 
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 голосов
/ 09 октября 2010

Я закончил делать это сейчас:

под моим объектом 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.Однако наши объекты перезаписываются каждый раз при загрузке, поэтому в худшем случае каждый объект в приложении может быть зарегистрирован один раз, даже если он не используется.

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

0 голосов
/ 08 октября 2010

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

0 голосов
/ 08 октября 2010

Вы можете попробовать пару вещей, таких как:

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

    Виджет сводки данных A

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

    Виджет манипулирования данными A

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

    Проверьте документацию здесь: http://api.jquery.com/bind/

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

...