Вопрос

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

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

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

Другие советы

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

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

  2. Используйте 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`

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

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

    Сводный виджет данных A

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

    Виджет Manipulation данных A

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

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

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

Вы пытались использовать live() Метод связывания?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top