2011-08-18 16 views
17

E 'tecnicamente possibile viste nido, utilizzando template, qualcosa di simile:Backbone.js: vista nidificazione attraverso template

<%= new PhotoCollectionView({model:new PhotoCollection(model.similarPhotos)}).render().el) %> 

posso mettere tutte le cose nel metodo di rendering, come pure, ma dà molto template più spazio per flessibilità e layout.

Ho provato la variante di cui sopra, ma tutto quello che ottengo di conseguenza sullo schermo è [HTMLDivElement].

Se provo a estrarre solo l'HTML fuori da esso, utilizzando l'HTML di jQuery, ottengo il rendering, ma risulta che i nodi DOM che vengono stampati sono diversi da quelli a cui le viste contengono un riferimento, perché nessuna interazione con quei nodi DOM è possibile usando l'istanza di visualizzazione. Ad esempio se all'interno della vista dico $(this.el).hide(), non accadrà nulla.

Qual è il modo corretto, se esiste?

+1

Non sono sicuro se questa tecnica sia tecnicamente possibile o meno, ma la raccomanderei contro, poiché i modelli dovrebbero contenere semplici istruzioni condizionali e non una qualsiasi logica applicativa. La logica dell'applicazione dovrebbe rimanere nelle tue visualizzazioni. In questo modo, c'è una chiara separazione delle preoccupazioni e la tua applicazione sarà più manutenibile. –

+0

è possibile nidificare le viste utilizzando React.js –

risposta

30

In genere, viene visualizzata per prima la vista padre. Quindi utilizzo il metodo this.$('selector') per trovare un elemento figlio che posso utilizzare come el della visualizzazione figlio.

Ecco un esempio completo:

var ChildView = Backbone.View.extend({ 
    //.. 
}) 

var ParentView = Backbone.View.extend({ 
    template: _.template($('#parent-template').html()), 
    initialize: function() { 
    _.bindAll(this, 'render'); 
    } 
    render: function() { 
    var child_view = new ChildView({ el: this.$('#child-el') }); //This refers to ParentView. 
    return this; 
    } 
}); 

var v = new ParentView(); 
v.render(); 
+0

beh, sì ... ho finito per fare lo stesso – user802232

+5

Questo sembra un po 'inefficiente. Stai inizializzando nuovamente la visualizzazione figlio ogni volta che viene eseguito il rendering del genitore. –

+4

D'accordo con Alessandro. Oltre ad essere inefficiente, perdi anche lo stato dinamico nelle viste secondarie ogni volta che viene visualizzata la vista genitore. Controlla [Backbone.Subviews] (https://github.com/rotundasoftware/backbone.subviews) per la soluzione minimalista pronta per l'uso –

1

Non conosco all'interno di un modello stesso, ma l'ho già fatto con tabelle ed elenchi. Nel modello esterno, basta avere lo stub:

<script type="text/template" id="table-template"> 
    <table> 
     <thead> 
      <th>Column 1</th> 
     </thead> 
     <tbody> 
     </tbody> 
    </table> 
</script> 

e per le singole voci: <% = field1%>

poi nel metodo di rendering, rendere le singole voci e li aggiunge all'elemento tbody ...

-1

La decisione di inizializzare un nuovo oggetto ogni volta che si esegue il rendering a me sembra molto inefficiente. In particolare questo:

render: function() { 
    var child_view = new ChildView({ el: this.$('#child-el') }); //This refers to ParentView. 
    return this; 
    } 

Idealmente, il rendering del genitore dovrebbe essere qualcosa di simile

render: function() { 
    this.$el.html(this.template()); 
    this.childView1.render(); 
    this.childView2.render(); 
} 

E la creazione bambini deve avvenire solo quando l'inizializzazione del genitore:

initialize: function() { 
     this.childView1 = new ChildView1(selector1); 
     this.childView2 = new ChildView2(selector2); 
} 

il problema è che non abbiamo selector1 e selector2 prima di rendere il modello principale. Questo è il punto in cui sono bloccato in questo momento :)

+1

Questo sembra non rispondere alla domanda, anche se il consiglio sembra ragionevole. Assicurati di rispondere effettivamente * alla domanda *! –

12

La risposta accettata ha un grosso difetto, che è il fatto che ChildView verrà reinizializzato ogni volta che viene reso. Ciò significa che si perderà lo stato e potenzialmente sarà necessario reinizializzare le viste complicate su ciascun rendering.

ho scritto un blog su questo qui: http://codehustler.org/blog/rendering-nested-views-backbone-js/

In sintesi, però, vi suggerirei di usare qualcosa di simile:

var BaseView = Backbone.View.extend({ 

    // Other code here... 

    renderNested: function(view, selector) { 
     var $element = (selector instanceof $) ? selector : this.$el.find(selector); 
     view.setElement($element).render(); 
    } 
}); 

var CustomView = BaseView.extend({ 

    // Other code here... 

    render: function() { 
     this.$el.html(this.template()); 
     this.renderNested(this.nestedView, ".selector"); 
     return this; 
    } 
}); 

Non è necessario estendere la vista Backbone se non lo fai vuoi, il metodo renderNested può essere messo ovunque tu voglia.

Con il codice sopra, è ora possibile inizializzare ChildView nel metodo di inizializzazione e quindi renderlo semplicemente quando viene chiamato il rendering().

2

Controllare il mixin Backbone.Subviews. È un mixin minimalista creato per gestire le viste nidificate e non reinizializza le viste secondarie ogni volta che viene eseguito il rendering del genitore.

Problemi correlati