Gestire gli eventi personalizzati jQuery
-
28-09-2019 - |
Domanda
Ho fatto un paio di ore di ricerca supplementare, ma ancora non riesce a trovare un buon motivo per quello che io penso è un problema comune.
Sto lavorando su un'applicazione .Net MVC2. La nostra applicazione è costituito da una pagina principale poi un certo numero di punti di vista parziali (pagine incluse) ognuna delle viste parziali corrisponde a un widget, comprensivi di un HTML struttura e JS-jQuery budella
Alcuni dei nostri widgets avere interazioni ricche con l'altro in modo ovviamente stiamo usando evento vincolante qualcosa del jQuery per l'effetto di questo:
Dati di sintesi Widget
$(document).bind("DataUpdated", summaryobject.updateTotals());
Data Manipulation Widget
$(document).trigger("DataUpdated");
Il problema che stiamo avendo è che quando un utente accede a parti delle applicazioni questi widget (HTML / DOM) vengono rimossi dalla pagina e sostituire con la nuova serie di viste parziali. Quando un utente si sposta indietro il codice HTML (rappresentazione visiva) viene ricaricato con il legame jQuery che crea un doppio legame.
Finora le mie soluzioni sembrano zoppo a me.
(1) si legano con l'oggetto DOM l'associazione è per:
$("#summaryobject").bind("DataUpdated", summaryobject.updateTotals());
Il problema di questo è che poi il mio innescando esigenze di widget per sapere cosa DOM riserva di trigger su:. $("#summaryobject")
che tipo di sconfitte lo scopo
(2) Creare un oggetto EventBus al tratto che legato quali eventi e consentire solo gli eventi da rilegare una volta. Il problema che sto avendo è quando la memorizzazione / vincolanti gli eventi non riesco a tenere traccia di chi lo ha creato in modo da non posso annullare la registrazione, se ho bisogno di .... forse gli eventi non registrati non è necessario evento.
Quali modelli sono altri che utilizzano per gestire gli eventi personalizzati?
Soluzione 4
ho finito per fare questo, per ora:
sotto il mio oggetto PageManager Ho scritto questo metodo
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);
}
}
}
Per la mia classe di widget ho fatto questo.
///<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);
};
Per ogni istanza di un widget si chiama registerForEvent a eventi bind.
Questo è lontano da una soluzione perfetta. Il nostro progetto avrà ancora perdite di memoria a che noi non annullare la registrazione i nostri oggetti JS. Tuttavia, i nostri oggetti vengono sovrascritte ogni volta che vengono caricati in modo caso peggiore è che ogni oggetto nell'applicazione può essere registrato una volta, anche se non vengono utilizzati.
Tuttavia, vincolante un metodo per una lega evento all'oggetto documento che non viene sovrascritto o corso. Quindi, questo codice ci impedirà di rebinding. Abbiamo ancora un po 'di una configurazione sciatta tuttavia è ramificazioni dovrebbero essere ridotti al minimo.
Altri suggerimenti
Ci sono due buone soluzioni al problema (che posso vedere).
-
Rimuovi tutte le chiamate
bind
e sostituirli con una singola chiamata adelegate
olive
e impostare un listener in ascolto per tutti di eventi che si verificano in l'applicazione e percorsi loro di luoghi appropriati. (In altre parole, creare un controller). -
Utilizzare un EventBus che consente eventi da non sottoscritti, così come sottoscritto. Il modo più semplice che ho visto a che fare questo con un EventBus è di Peter Michaux Eventing sceneggiatura .
/*
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;
};
Un esempio di utilizzo di questo secondo metodo sarebbe:
EventManager.subscribe("DataUpdated", summaryobject, "updateTotals");
// ... at some point later on ...
EventManager.fire("DataUpdated");
// Fires `updateTotals` with `this` bound to `summaryobject`
Si potrebbe provare un paio di cose, come:
-
namespacing i tipi di eventi. In questo modo, pur non creando un legame tra due casi vista specifici, è possibile creare un rapporto generalizzato tra i tipi di viste. Dal tuo Nell'esempio qui sopra:
Dati di sintesi Widget A
$(document).bind("DataUpdated.Statistics", summaryobject.updateTotals());
Data Manipulation Widget A
$(document).trigger("DataUpdated.Statistics");
Controlla la documentazione qui: http://api.jquery.com/bind/
-
scarico dei gestori di eventi ogni volta che un widget o gruppo di esse viene scaricata, prima di caricare il nuova DOM / gestori.
Hai provato a usare live()
metodo di rilegatura?