Backbone: 正在调用视图的渲染方法但 DOM 未更新
Backbone: view's render method being called but DOM not updating
请看这个 jsfiddle:https://jsfiddle.net/76bypu9d/
如您所见,我有一份兼具力量、灵巧和智慧的球员名单。当我点击更新按钮时,我根据输入计算点数。
然而,PlayerView 没有被重新渲染,尽管我已经让视图监听模型的变化:
var PlayerView = Backbone.View.extend({
tagName: "<tr>",
initialize: function() {
_.bindAll(this, "render");
this.listenTo(this.model, "change", this.render);
},
render: function() {
var html = "<td>" + this.model.get("name") + "</td>";
html += "<td>" + this.model.get("job") + "</td>";
html += "<td>" + this.model.get("str") + "</td>";
html += "<td>" + this.model.get("dex") + "</td>";
html += "<td>" + this.model.get("int") + "</td>";
html += "<td>" + this.model.get("points") + "</td>";
$(this.el).html(html);
return this;
}
});
我可以在控制台中看到模型正在使用新值更新,并且正在调用视图的渲染方法,但 DOM 中的值没有改变。有什么想法吗?
这是因为您没有在 DOM 中插入 PlayerView
el
。您将每个渲染为一个字符串并将其连接起来以渲染 PlayerTableView
。因此,文档中的元素与 PlayerView
的 el
属性之间没有任何联系。您应该返工 PlayerTableView.render()
以插入 PlayerView.el
。
这里有一个与您的代码的快速差异来说明:
https://jsfiddle.net/76bypu9d/6/
之前:
html += "</thead><tbody>";
_(this.collection.models).each(function( player) {
var playerView = new PlayerView({
model: player
})
html += playerView.render().el.outerHTML;
}, this);
html += "</tbody></table>";
$(this.el).html(html);
之后:
html += "</thead><tbody>";
html += "</tbody></table>";
$(this.el).html(html);
_(this.collection.models).each(function( player) {
var playerView = new PlayerView({
model: player
})
this.$el.find("tbody").append(playerView.render().el);
}, this);
顺便说一下,那个字符串连接很可怕。你应该研究像 mustache 这样的模板引擎。
其他
这里有一些关于您的 Backbone 代码其他方面的杂项说明:
回复:tagName: "<tr>"
、tagName
不需要尖括号 (<
>
)。我想它有效,但这不是必需的。可以是tagName: "tr"
这:_.bindAll(this, "render")
可能不是必需的,而且对于以下行来说绝对不是必需的:this.listenTo(this.model, "change", this.render)
。来自 backbone 文档:
The callback
will always be called with object
as context.
在这种情况下,object
是 this
。
你的 PlayerTableView
和 _.bindAll(this, "render", "updatePoints")
也一样。指定的事件处理程序如下:
events: {
"click button": "updatePoints"
},
将以视图对象作为上下文调用。
Re: $(this.el).html(html)
-- $(this.el)
是不必要的。你可以做 this.$el
.
这个:
playersData.forEach(function( playerData ) {
var player = new Player();
player.set({
name: playerData.name,
job: playerData.job,
str: playerData.str,
dex: playerData.dex,
int: playerData.int
});
that.collection.add(player);
可以合并到这个(因为你设置了PlayerCollection.model
):
that.collection.add(playersData);
这个: _(this.collection.models).each()
可以是 this.collection.each()
.
值得重复,必须进行字符串连接。
请看这个 jsfiddle:https://jsfiddle.net/76bypu9d/
如您所见,我有一份兼具力量、灵巧和智慧的球员名单。当我点击更新按钮时,我根据输入计算点数。
然而,PlayerView 没有被重新渲染,尽管我已经让视图监听模型的变化:
var PlayerView = Backbone.View.extend({
tagName: "<tr>",
initialize: function() {
_.bindAll(this, "render");
this.listenTo(this.model, "change", this.render);
},
render: function() {
var html = "<td>" + this.model.get("name") + "</td>";
html += "<td>" + this.model.get("job") + "</td>";
html += "<td>" + this.model.get("str") + "</td>";
html += "<td>" + this.model.get("dex") + "</td>";
html += "<td>" + this.model.get("int") + "</td>";
html += "<td>" + this.model.get("points") + "</td>";
$(this.el).html(html);
return this;
}
});
我可以在控制台中看到模型正在使用新值更新,并且正在调用视图的渲染方法,但 DOM 中的值没有改变。有什么想法吗?
这是因为您没有在 DOM 中插入 PlayerView
el
。您将每个渲染为一个字符串并将其连接起来以渲染 PlayerTableView
。因此,文档中的元素与 PlayerView
的 el
属性之间没有任何联系。您应该返工 PlayerTableView.render()
以插入 PlayerView.el
。
这里有一个与您的代码的快速差异来说明: https://jsfiddle.net/76bypu9d/6/
之前:
html += "</thead><tbody>";
_(this.collection.models).each(function( player) {
var playerView = new PlayerView({
model: player
})
html += playerView.render().el.outerHTML;
}, this);
html += "</tbody></table>";
$(this.el).html(html);
之后:
html += "</thead><tbody>";
html += "</tbody></table>";
$(this.el).html(html);
_(this.collection.models).each(function( player) {
var playerView = new PlayerView({
model: player
})
this.$el.find("tbody").append(playerView.render().el);
}, this);
顺便说一下,那个字符串连接很可怕。你应该研究像 mustache 这样的模板引擎。
其他
这里有一些关于您的 Backbone 代码其他方面的杂项说明:
回复:
tagName: "<tr>"
、tagName
不需要尖括号 (<
>
)。我想它有效,但这不是必需的。可以是tagName: "tr"
这:
_.bindAll(this, "render")
可能不是必需的,而且对于以下行来说绝对不是必需的:this.listenTo(this.model, "change", this.render)
。来自 backbone 文档:The
callback
will always be called withobject
as context.在这种情况下,
object
是this
。你的
PlayerTableView
和_.bindAll(this, "render", "updatePoints")
也一样。指定的事件处理程序如下:events: { "click button": "updatePoints" },
将以视图对象作为上下文调用。
Re:
$(this.el).html(html)
--$(this.el)
是不必要的。你可以做this.$el
.这个:
playersData.forEach(function( playerData ) { var player = new Player(); player.set({ name: playerData.name, job: playerData.job, str: playerData.str, dex: playerData.dex, int: playerData.int }); that.collection.add(player);
可以合并到这个(因为你设置了
PlayerCollection.model
):that.collection.add(playersData);
这个:
_(this.collection.models).each()
可以是this.collection.each()
.值得重复,必须进行字符串连接。