2012-03-01 13 views
19

Tengo un PageView de nivel superior que se volverá a representar cada vez que cambie la ruta. Tengo muchas sub-vistas anidadas incrustadas en este PageView. Si tuviera que volver a procesar PageView, ¿debo quitar/desvincular todas las subvistas anidadas junto con PageView o solo tengo que quitar/desvincular el PageView? Si necesito eliminar/desvincular todas las sub-vistas, ¿cuál es la mejor manera de hacerlo?Backbone.js - Eliminar todas las vistas secundarias

+0

¿Qué quiere decir con desvinculación de subvistas? ¿Te refieres a eventos? – Trevor

Respuesta

35

Sí, tiene que quitar correctamente y desenlazar ellos:

http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

La manera más fácil de hacer esto es para almacenar una gran variedad de sus sub-puntos de vista en la vista padre. Luego, en un método close en la vista padre, recorrer la matriz y llamar a un método close en las vistas secundarias:

ParentView = Backbone.View.extend({ 
    initialize: function(){ 
    this.childViews = []; 
    }, 

    render: { 
    for (var i = 0; i < 10; i++){ 
     var childView = new ChildView(); 
     // do stuff with the child view 
     this.childViews.push(childView); 
    } 
    }, 

    close: function(){ 
    this.remove(); 
    this.unbind(); 
    // handle other unbinding needs, here 
    _.each(this.childViews, function(childView){ 
     if (childView.close){ 
     childView.close(); 
     } 
    }) 
    } 
}); 

Asegúrese de llamar al método close en la vista padre cuando esté listo para que sea eliminado/reemplazado. Esto asegurará que todos los niños se limpien correctamente (suponiendo que todos ellos tengan su propio método close).

+0

Hola, Derick, he seguido tu consejo sobre esto, pero estoy experimentando demoras realmente largas al cerrar una vista + es vistas de niños. En algunos casos, puede durar entre 5 y 10 segundos. Parece que el retraso viene de this.remove(). ¿Tienes alguna idea de por qué? – ragulka

+0

¡es bastante largo y horrible! Nunca lo he visto, honestamente ... ¿Qué tan grande es la estructura DOM que estás eliminando? Mi única conjetura sería un navegador realmente lento, y/o un conjunto de nodos DOM muy grande. –

+0

Oye, no importa, parece que es un problema con un complemento jquery que de alguna manera está en conflicto con la función remove() de la vista: http://stackoverflow.com/questions/9877786/calling-jquery-remove-on-custom-ui -widget-causes-infinite-loop/9878287 # 9878287 – ragulka

2

En lugar de mantener una vista de matriz de elementos secundarios, podría recorrer todas las propiedades de la vista y ver cuáles son una instancia de Backbone.View; Deberá asegurarse de establecer una propiedad para cada vista secundaria en su vista principal.

En el ejemplo siguiente, las vistas secundarias se establecen en las propiedades de la vista principal. No estoy seguro de cuál será el rendimiento al recorrer todas las propiedades, sin embargo, puede ser más fácil que hacer un seguimiento de una estructura de datos separada para las vistas secundarias.

Ejemplo:

var ContextView = Backbone.View.extend({ 
    initialize: function() { 
     // views render themselves via their initialize methods 
     this.titlebar = new TitlebarView({el: $("#titlebar")});  
     this.toolbar = new ToolbarView({el: $("#toolbar")}); 
     this.content = new ContentView({el: $("#content")}); 
    }, 
    removeChildViews: function() {  
     for(var prop in this){ 
      if (this[prop] instanceof Backbone.View) { 
       console.log("This is a view: "+ prop + ' in ' + this[prop]);  
      } 
     } 
    }, 
    render: function() { 
     this.$el.html(this.el); 
    } 
    }); 
3

una clase simple y modular que pueda ser útil.

ContainerView = Backbone.View.extend({ 
    initialize: function() { 
    this.children = []; 
    }, 
    remove: function() { 
    Backbone.View.prototype.remove.apply(this, arguments); 
    this.removeAllChildren(); 
    }, 
    removeAllChildren: function() { 
    _.each(this.children, function(view) { view.remove(); }); 
    this.children = []; 
    }, 
    appendAllChildren: function() { 
    _.each(this.children, function(view) { this.$el.append(view.render().$el); }, this); 
    } 
}); 

uso:

MyView = ContainerView.extend({ 
    render: function() { 
    this.removeAllChildren(); 
    this.$el.empty(); 

    // For each child view... 
    // this.children.push(new SomeControl(...)); 

    this.appendAllChildren(); 
    return this; 
    } 
}); 
0

Un poco como Zengineer escribió, me gusta parchear Backbone.View.remove globalmente como la siguiente, de modo que los puntos de vista para niños fijado en este se eliminan

var originalRemove = Backbone.View.prototype.remove; 

Backbone.View.prototype.remove = function() 
{ 

    for (var view in this){ 
    if (this[view] instanceof Backbone.View && this[view] != this) { 
     this[view].remove(); 
    } 
    } 


    originalRemove.apply(this, arguments); 

} 
Cuestiones relacionadas