一个简单的演示:
var PersonListView = Backbone.View.extend({
initialize: function () {
this.listenTo(this.collection, 'add', this.addOne);
this.listenTo(this.collection, 'reset', this.addAll);
},
addOne: function (model) {
var subView = new PersonItemView({model: model});
$(this.el).append(subView.render().el);
},
addAll: function () {
$(this.el).empty();
this.collection.each(this.addOne, this);
},
render: function () {
this.addAll();
return this;
}
});
var PersonItemView = Backbone.View.extend({
template: _.template($('#tpl_person_item').html()),
initialize: function () {
this.listenTo(this.model, 'remove', this.remove);
this.listenTo(this.model, 'change', this.render);
},
render: function () {
console.info("render person:" + this.model.get("name"));
var el = $(this.template(this.model.toJSON()));
this.setElement(el);
return this;
}
});
var p = new Person({name: 'name1'});
var ps = new PersonList();
ps.add(p);
new PersonListView({
el: $("#list"),
collection: ps
}).render();
setTimeout(function () {
p.set("name", "new name")
}, 5000);
如图所示,我通过以下方式将模型的change
事件绑定到视图:
this.listenTo(this.model, 'change', this.render);
但是,尽管调用了 render
方法,但元素不会更新到页面。
似乎setElement
并没有将其el
添加到 dom 中。
如何解决这个问题?
我对 Backbone 有点生疏,我对此作为解决方案并不完全满意,但这有效:将PersonItemView
类更改为如下所示:
var PersonItemView = Backbone.View.extend({
template: _.template($('#tpl_person_item').html()),
initialize: function () {
this.el = null;
this.listenTo(this.model, 'remove', this.remove);
this.listenTo(this.model, 'change', this.render);
},
render: function () {
console.info("render person:" + this.model.get("name"), this.el);
if (this.el == null) {
var el = $(this.template(this.model.toJSON()));
this.setElement(el);
}
else {
$(this.el).replaceWith($(this.template(this.model.toJSON())));
}
return this;
}
});
也许更好的解决方案是让PersonListView.addOne
创建一个空的<li>
元素并将其传递给PersonItemView
的构造函数,然后PersonItemView.render
总是可以使用replaceWith
。
当您更改模型时,仅执行 PersonItemView 的渲染。该函数正在更改视图的 el,但不根据您的代码更新 DOM。
由于您仅在集合视图中更新 DOM,因此即使在单个模型中进行更改时,只需呈现完整的集合
var PersonListView = Backbone.View.extend({
initialize: function () {
this.listenTo(this.collection, 'add', this.addOne);
this.listenTo(this.collection, 'reset', this.addAll);
this.listenTo(this.collection, 'change', this.addAll);
},
捷轩
解决方案 2:setElement 覆盖了元素的 el,因此您正在更新不在 DOM 中的元素。 所以不要使用 setElement 而只是更新相同的 el。
var PersonItemView = Backbone.View.extend({
render: function () {
console.info("render person:" + this.model.get("name"));
this.$el.html(this.template(this.model.toJSON());
return this;
}
});
如果你想使用 setElement,请确保你再次将 el 添加到 DOM 中。 这在你的代码中没有发生。