2010-10-08 117 views
2

我已經做了幾個小時的額外研究,但我仍然無法找到一個好的模式,我認爲這是一個常見問題。Managaing jQuery自定義事件

我正在處理.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 bject來觸發:$("#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電話,併到delegatelive一個調用替換它們,併成立了一個偵聽所有發生在你的應用程序,並將它們路由到適當的地方事件的監聽器。 (換句話說,創建一個控制器)。

  2. 使用一個EventBus,它允許事件取消訂閱以及訂閱。我看到用EventBus做這件事最簡單的方法是Peter Michaux的Eventing script


/* 
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內置事件綁定的更復雜版本?我不太瞭解火法,但我想我知道它在做什麼。 – 2010-10-08 19:00:09

+0

@Chris - 選項#2實際上完全獨立於任何JavaScript庫。它創建了一個事件的中心註冊表,並允許任何知道它的事物爲事件添加「監聽者」。無論何時調用fire,它都會檢查註冊表('EventManager.events')是否包含按期望名稱的鍵。如果確實如此,它將在數組上運行並調用事件數組中的每個函數。 – 2010-10-08 19:16:55

+0

哦,我現在看得更清楚了。我其實並沒有真正看到這是如何解決雙重綁定的問題。這只是基本上重新創建了Jquery事件總線。 jQuery通過bind/unbind提供了相同的功能。我也沒有看到自定義綁定的好處。那麼我看到一個好處,但沒有解決這個問題的人。我認爲我的問題實際上是應用程序工作方式的總體設計。我們需要更聰明地瞭解我們如何加載我們的JS對象並執行綁定。我有一個臨時解決方案,但我們必須做一個主要的重構才能正確。我會思考這個雖然 – 2010-10-08 19:46:08

0

你可以嘗試一些東西,比如:

  1. 命名空間的事件類型。 這樣,雖然不是 創建兩個 特定視圖實例之間的綁定,您可以在 之間創建一個廣義關係 視圖類型之間。從你的 上面的例子:

    數據摘要小部件

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

    數據操作窗口小部件

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

    查覈在這裏的文檔: http://api.jquery.com/bind/

  2. 卸載的事件處理程序 每當一個部件或他們的組在加載 新DOM /處理程序之前,卸載。

+0

觸發小部件仍然需要調用「DataUpdated.Statistics」,它緊密結合兩者,就像綁定到特定的DOM對象一樣。 – 2010-10-08 17:56:45

0

您是否嘗試過使用live()的綁定方法?

+0

現場看起來很酷,但從我最初的看起來,它看起來像活非常適合非自定義事件。但是,我的客戶事件綁定到保持註冊的JS對象。 – 2010-10-08 17:46:35

+0

抱歉,我沒有發佈最後的評論。但無論如何只是爲了闡述。生活並不能解決問題,但我認爲這可能是一種更好的方式,而不僅僅是綁定。 – 2010-10-08 17:54:31