backbone.js - ¿Hay alguna manera de vincular el activador.change() de un Modelo a la función.render() de una Vista sin crear más de uno?
(5)
A partir de Backbone 0.9.2 (y posiblemente antes), la función on()
o bind()
(así como su contraparte off()
o unbind()
) toma un parámetro de context
opcional para usarlo cuando se le llama.
Asi que,
SomeView = Backbone.View.extend({
initialize: function(){
_.bindAll(this, "render");
this.model.bind(''change'', this.render);
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
puede llegar a ser
SomeView = Backbone.View.extend({
initialize: function(){
this.model.bind(''change'', this.render, this);
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
Consulte la documentación de on()
.
Una vista normalmente espera un objeto con estos atributos antes de que pueda representarse:
{ el: ''#someelement'', model: someModel }
Una Vista también nos permite vincular los eventos del modelo a funciones en la vista:
initialize: function() {
this.model.bind(''change'', this.renderFromModel, this);
},
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
return this;
},
renderFromModel: function() {
var t = _.template($(''#some-template'').html());
$(''item-'' + this.cid).html(t(this.toJSON()));
return this;
},
El problema es que la primera vez que instanciamos una Vista para renderizar, está esperando un objeto con un Modelo; y la segunda vez que renderizamos la vista cuando es llamada desde dentro del Modelo, no lo es. Debido a esto, termino creando dos funciones render ().
¿Hay una mejor manera de lograr un único elemento de representación que también pueda responder a los eventos de model.change ()?
Creo que debes asegurarte de que tu método de renderización siempre esté vinculado a la vista llamando al método bindAll de underscore.js.
SomeView = Backbone.View.extend({
initialize: function(){
_.bindAll(this, "render");
this.model.bind(''change'', this.render);
},
render: function(){
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
Una mejor solución es usar la función listenTo :
SomeView = Backbone.View.extend({
initialize: function(){
this.listenTo(this.model, ''change'', this.render);
},
render: function(){
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
De esta forma, el objeto de vista es consciente de los enlaces que realizó, y todos ellos se pueden eliminar con la función stopListening y no necesita llamar bind o bindAll explícitamente. Por último, pero no menos importante, el código es más limpio en mi opinión.
Use el método _.bind () para establecer el alcance
this.model.bind(''change'', _.bind(this.render, this));
crear instancia de modelo en la vista
var myapp.myView = new View({
model: new Model
});
y cuando inicialice Backbone.View inside add this ... qué render se llamará cada vez que haya cambios en los atributos del modelo de sus valores predeterminados
this.model.bind(''change'', this.render,this)