wake-up-neo.com

backbone.js strukturiert verschachtelte Ansichten und Modelle

Verwenden von backbone.js:

Ich habe ein Top-Level-Modell A, das 2 Attribute und 2 verschachtelte Modelle enthält, ModelB und ModelC. ModelB und ModelC haben jeweils zwei Attribute:

ModelA
    attributeA1
    attributeA2
    ModelB
        attributeB1
        attributeB2
    ModelC
        attributeC1
        attributeC2

Es gibt ein ViewA für ModelA und ein ViewB für ModelB. Die Render-Funktion von ViewA platziert ein neues div auf dem Body, während ViewBs Render ein h1 erzeugt. Die Initialisierung von ViewA ruft das Rendering von ViewB auf, um dieses h1 in das neue div einzufügen. Der Grund für diese Trennung ist, dass sich der h1 möglicherweise ändert und unabhängig von ViewA ein erneutes Rendern erfordert.

ViewA
    initialise: 
        //call ViewA's own render function
        this.render() 

        //call ViewB's render function that further modifies the $("#new") div created earlier.
        $("#new").append(ViewB.render().el)

    //ViewA's own render function
    render: //place <div id="new"></div> onto 'body'

ViewB
    render: //create a <h1></h1>
    funcB1: //can this access it's parent ModelA's attributes and other objects?

Q1: ViewB hat eine Funktion funcB1. Kann diese Funktion auf die Attribute des übergeordneten Modells zugreifen? Attribute wie attributeA1 oder sogar attributeC1 (was wäre ein Geschwister/Cousin)?

F2: Kann funcB1 als weitere Erweiterung zu Q1 auf die mit ViewA verknüpften DOM-Elemente zugreifen? (in diesem Beispiel das #new div?)

F3: Wie definiere ich im Allgemeinen die oben beschriebenen Verknüpfungen zwischen Ansichten und Modellen, damit alles ordnungsgemäß zusammenarbeitet?

Mir ist klar, dass diese Frage etwas abstrakt ist, aber jeder weiß Hilfe oder Richtlinien zu schätzen.

71
fortuneRice

Um Attribute für verwandte Modelle zu erhalten, muss das Modell über Kenntnisse darüber verfügen, mit welchen Modellen es verwandt ist. Backbone.js befasst sich nicht implizit mit Beziehungen oder Verschachtelungen. Sie müssen also selbst sicherstellen, dass die Modelle einander kennen. Um Ihre Fragen zu beantworten, müssen Sie sicherstellen, dass jedes untergeordnete Modell über ein übergeordnetes Attribut verfügt. Auf diese Weise können Sie die Verschachtelung zuerst bis zum übergeordneten Element und dann bis zu allen Ihnen bekannten Geschwistern durchlaufen.

Um genauer mit Ihren Fragen zu sein. Wenn Sie modelA initialisieren, erstellen Sie wahrscheinlich modelB und modelC. Ich würde vorschlagen, dass Sie dabei eine Verknüpfung zum übergeordneten Modell herstellen:

ModelA = Backbone.Model.extend({

    initialize: function(){
        this.modelB = new modelB();
        this.modelB.parent = this;
        this.modelC = new modelC();
        this.modelC.parent = this;
    }
}

Auf diese Weise können Sie das übergeordnete Modell in einer beliebigen untergeordneten Modellfunktion erreichen, indem Sie this.parent aufrufen.

In Bezug auf Ihre Ansichten finde ich es einfacher, wenn Sie verschachtelte Backbone-Ansichten ausführen, dass jede Ansicht ein HTML-Tag darstellt, indem Sie die Option tagName der Ansicht verwenden. Ich würde Ihre Ansichten so schreiben:

ViewA = Backbone.View.extend({

    tagName: "div",
    id: "new",

    initialize: function(){
       this.viewB = new ViewB();
       this.viewB.parentView = this;
       $(this.el).append(this.viewB.el);
    }
});

ViewB = Backbone.View.extend({

    tagName: "h1",

    render: function(){
        $(this.el).html("Header text"); // or use this.options.headerText or equivalent
    },

    funcB1: function(){
        this.model.parent.doSomethingOnParent();
        this.model.parent.modelC.doSomethingOnSibling();
        $(this.parentView.el).shakeViolently();
    }

});

Dann würde ich in Ihrem Anwendungsinitialisierungscode (z. B. in Ihrem Controller) ViewA initiieren und sein Element im body-Element platzieren.

73
Jens Alm

Die obige Lösung ist auf dem richtigen Weg, hat aber einige Probleme.

initialize: function(){
  this.viewB = new ViewB();
  this.viewB.parentView = this;
  $(this.el).append(this.viewB.el);    
}

Hauptsächlich gibt toJSON () des Modells jetzt veraltete Daten zurück. Ich habe eine Lösung zur Behebung dieses Problems in einem backbone.js-Plugin gepostet. Du kannst es gerne benutzen.

3
geddesign

Die allgemeine Antwort auf die Frage "Kann ich" lautet immer "Ja, solange Sie bereit sind, den Code zu schreiben". Das Ziel von Backbone ist eine starke Trennung von Modell und Ansicht. Wenn B1 einen Verweis auf A1 und A1 einen Verweis auf C1 enthält, können Sie Methoden erstellen und Regeln festlegen, nach denen B1 A1 und C1 ändern kann.

Die Ansichten sollten so eingerichtet sein, dass sie CRUD-Ereignisse von ihren jeweiligen Modellen empfangen. Wenn der Benutzer mit B1view etwas unternimmt, das B1model ändert, und B1model wiederum A1model ändert, sollte A1model ein Ereignis generieren, das A1view empfängt, und ein erneutes Rendern von A1view usw. veranlassen. Es sollte wie durch Zauberei geschehen. (In der Praxis dauert es einige Zeit, bis die Magie stimmt, aber ich habe festgestellt, dass Backbone wirklich mächtig ist. Und BackboneRelational hilft bei Dingen wie dem, was Sie hier beschreiben.)

3
Elf Sternberg

Sie können einige Erweiterungen verwenden, z. B. Backbone-Formulare https://github.com/powmedia/backbone-formulare . Um Ihrem Anwendungsfall zu folgen, definieren Sie ein Schema wie:

var ModelB = Backbone.Model.extend({
    schema: {
        attributeB1: 'Text',
        attributeB2: 'Text'
    }
});

var ModelC = Backbone.Model.extend({
    schema: {
        attributeC: 'Text',
    }
});

var ModelA = Backbone.Model.extend({
    schema: {
        attributeA1: 'Text',
        attributeA2: 'Text',
        refToModelB: { type: 'NestedModel', model: ModelB, template: 'templateB' },
        refToModelC: { type: 'NestedModel', model: ModelC, template: 'templateC' }
    }
});

Unter https://github.com/powmedia/backbone-forms#customising-templates finden Sie Teilvorlagen.

Wichtige Teile hier sind type: 'NestedModel' und template: 'templateXXX'.

Dieses Plugin hat einige Einschränkungen, aber Sie können sich andere unter https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources ansehen.

2
Artem Oboturov

Es gibt das Backbone-Plugin Backbone-relational.js, das Eins-zu-Eins-, Eins-zu-Viele- und Viele-zu-Eins-Beziehungen zwischen Modellen für Backbone bereitstellt.

Ich denke, dies wird Ihre Bedürfnisse erfüllen. Vist BackboneRelational für weitere Dokumentation.

0
Gagan