2012-04-02 8 views
44

In meinem einfachen Projekt habe ich 2 Ansichten - eine Werbebuchung (Marke) und App. Ich habe Funktion hinzugefügt, die die Auswahl mehrerer Elemente ermöglicht:Backbone JS: Kann man Aktualisierungen in anderen Ansichten auslösen?

 
var BrandView = Backbone.View.extend({ 
...some code... 
    toggle_select: function() { 
     this.model.selected = !this.model.selected; 
     if(this.model.selected) $(this.el).addClass('selected'); 
     else $(this.el).removeClass('selected'); 
     return this; 
    } 
}); 

var AppView = Backbone.View.extend({ 
...some code... 
    delete_selected: function() { 
     _.each(Brands.selected(), function(model){ 
      model.delete_selected(); 
     }); 
     return false; 
    }, 
}); 

Das ist, möchte ich wissen, wie viele Elemente ausgewählt sind. Bei dieser Einstellung wirkt sich die Auswahl NICHT auf das Modell aus und löst somit keine Ereignisse aus. Und vom MVC-Konzept verstehe ich, dass Ansichten nicht direkt mit anderen Ansichten kommunizieren sollen. Wie kann AppView wissen, dass in BrandViews etwas ausgewählt wird?

Und genauer, ich AppView zu wissen, wie viele Elemente ausgewählt wurden, wenn also mehr als 1 ausgewählt ist, zeige ich ein Menü für die Mehrfachauswahl.

+2

BTW, '$ (this.el) .toggleClass ("ausgewählt")'. Oder noch kürzer zu 'this.model.selected = $ (this.el) .toggleClass ('selected'). HasClass (" selected ");.. –

Antwort

71

Sie könnten eine Lese dieser Diskussion von Backbone pub/sub Ereignisse haben wollen:

http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/

Ich mag es hinzuzufügen, in als globaler Event-Mechanismus:

Backbone.pubSub = _.extend({}, Backbone.Events); 

Dann in einer Ansicht können Sie ein Ereignis auslösen:

Backbone.pubSub.trigger('my-event', payload); 

Und in einem anderen können Sie hören:

Backbone.pubSub.on('my-event', this.onMyEvent, this); 
+0

Eigentlich ist das genau das, was ich irgendwann gelesen habe http://losechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/ und begann damit. Gute Sache. Danke) –

+0

Das hat mir wirklich geholfen Wir haben eine große Zeit, Danke, – Bharat

+0

Dito Kommentar oben .. vielen Dank! – Alex

1

Ignorieren Sie die Probleme damit, die Sie bereits in Ihrem Post erwähnen, können Sie Ereignisse an/von dem globalen Backbone.Event-Objekt binden und auslösen, was alles mit irgendetwas anderem sprechen lässt. Definitiv nicht die beste Lösung, und wenn Sie Ansichten haben, die miteinander chatten, dann sollten Sie darüber nachdenken, das zu refactoring. Aber da gehst du! Hoffe das hilft.

7

Ich benutze, was Addy Osmani das Mediatormuster http://addyosmani.com/largescalejavascript/#mediatorpattern nennt. Der ganze Artikel ist eine Lektüre wert.

Im Grunde handelt es sich um einen Ereignismanager, mit dem Sie Ereignisse abonnieren und veröffentlichen können. Ihr AppView würde also zu einem Ereignis, d. H. "Ausgewählt", einen Index erstellen. Dann würde das BrandView das "ausgewählte" Ereignis veröffentlichen.

Der Grund dafür ist, dass Sie Ereignisse zwischen Ansichten senden können, ohne dass die Ansichten direkt miteinander verbunden sind.

Für Beispiel

var mediator = new Mediator(); //LOOK AT THE LINK FOR IMPLEMENTATION 

var BrandView = Backbone.View.extend({ 
    toggle_select: function() { 
     ... 
     mediator.publish('selected', any, data, you, want); 
     return this; 
    } 
}); 

var AppView = Backbone.View.extend({ 
    initialize: function() { 
     mediator.subscribe('selected', this.delete_selected) 
    }, 

    delete_selected: function(any, data, you, want) { 
     ... do something ... 
    }, 
}); 

Auf diese Weise Ihre App Ansicht kümmert sich nicht darum, ob es ein BrandView oder FooView ist, der die ‚ausgewählt‘ Ereignis veröffentlicht, nur, dass das Ereignis aufgetreten ist. Daher halte ich es für eine wartungsfreundliche Möglichkeit, Ereignisse zwischen Teilen Ihrer Anwendung zu verwalten, nicht nur Ansichten.

Wenn Sie weiter über die 'Fassade' lesen, können Sie eine nette Berechtigungsstruktur erstellen. Dadurch können Sie sagen, dass nur ein "AppView" mein "ausgewähltes" Ereignis abonnieren kann. Ich finde das hilfreich, da es sehr deutlich macht, wo die Ereignisse verwendet werden.

+0

Wird dies nativ in Backbone unterstützt? –

+0

Es ist nicht Teil von Backbone , deshalb mag ich das. Wenn Sie ein DOM-Ereignis in einer Ansicht direkt an eine andere Ansicht binden würden, die beim Versuch, Ihre Ansichten zu ändern, sehr verwirrend sein würde, werde ich meine Antwort aktualisieren, um zu verdeutlichen, was ich meine. –

0

Verwenden Sie die gleichen Modellobjekte. AppView konnte mit einer Sammlung initialisiert und BrandView mit einem Modell aus dieser Sammlung initialisiert werden. Wenn sich Attribute eines Zweigobjekts ändern, kann jeder andere Code, der eine Referenz auf dieses Modell hat, diese lesen.

So können, so dass Sie einige Marken, die Sie über eine Sammlung holen:

var brands = new Brands([]); 
brands.fetch(); 

Jetzt haben Sie eine AppView machen, und eine Reihe von BrandView ist für jedes Modell.

var appView = new AppView({brands: brands}); 
var brandViews = brands.map(function(brand) { 
    return new BrandView({brand: brand}); 
}); 

Die AppView und die brandViews jetzt haben beide Zugriff auf die gleichen Modellobjekte, also wenn Sie ein ändern:

brands.get(0).selected = true; 

Dann ändert sie, wenn sie von den Ansichten zugegriffen, die es auch verweisen.

console.log(appView.brands.get(0).selected); // true 
console.log(brandViews[0].brand.selected) // true 
+0

Ihre ersten 2 Codebeispiele werden bereits verwendet, und ich weiß, wie man die Anzahl ausgewählter Marken bekommt. Die Frage war, wie man eine Ansicht in einer anderen Ansicht aktivieren/deaktivieren kann. –

0

Gleiche wie John oben vorgeschlagen hat, wieder die Mediator-Muster funktioniert wirklich gut in diesem Szenario als Addy Osmani dieses Problem zusammenfassend in Backbone fundamentals.

die Backbone.Mediator Plugin aufgewickelt, die einfach und groß ist, und macht meine AMD Ansicht Module nahtlos zusammen arbeiten =)

1

Hier meinem Fall mit einem ähnlichen Bedarf: Backbone listenTo schien eine Lösung einzuloggen zu umleiten Seite für zeitlich begrenzte oder nicht authentifizierte Anfragen.

ich hinzugefügt Event-Handler zu meinem Router und machte es zum globalen Ereignis hören wie:

Backbone.Router.extend({ 
    onNotAuthenticated:function(errMsg){ 
     var redirectView = new LoginView(); 
     redirectView.displayMessage(errMsg); 
     this.loadView(redirectView); 
    }, 
    initialize:function(){ 
     this.listenTo(Backbone,'auth:not-authenticated',this.onNotAuthenticated); 
    }, 
    ..... 
}); 

und in meinem Jquery AJAX-Fehler-Handler:

$(document).ajaxError(
    function(event, jqxhr, settings, thrownError){ 
     ....... 
     if(httpErrorHeaderValue==="some-value"){ 
      Backbone.trigger("auth:not-authenticated",errMsg); 
     } 
    });  
+0

In Ort, wo Backbone.on() nicht funktionieren würde this.listenTo() gearbeitet ... –

1

Sie können Backbone verwenden Objekt als Event-Bus.

Dieser Ansatz ist etwas sauberer, aber setzt weiterhin auf globales Backbone Objekt obwohl

var view1 = Backbone.View.extend({ 

    _onEvent : function(){ 
    Backbone.trigger('customEvent'); 
    } 

}); 


var view2 = Backbone.View.extend({ 

    initialize : function(){ 
    Backbone.on('customEvent', this._onCustomEvent, this); 
    }, 

    _onCustomEvent : function(){ 
    // react to document edit. 
    } 

}); 
Verwandte Themen