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。因此,文档中的元素与 PlayerViewel 属性之间没有任何联系。您应该返工 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.

    在这种情况下,objectthis

    你的 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().

  • 值得重复,必须进行字符串连接。