backbone.js - 渲染视图

11

我的 ListClass 看起来像这样:

var ListView = Backbone.View.extend({

    initialize: function() {
        this.render();
    },  

    events: {
        'click ul#perpage span': 'setperpage'
    },

    setperpage: function(event) {
        this.collection.perpageurl = '/perpage/' + $(event.target).text();
        this.collection.fetch();
        this.render();
    },

    render: function() {

    template = _.template('\
    <table>\
    <% _(collection).each(function(model){%>\
    <tr><td><%=model.id%></td><td><%=model.name%></td><td><%=model.email%></td></tr>\
    <%}); %>\
    </table>\
    <ul id="perpage">\
    <li><span>5</span></li>\
    <li><span>10</span></li>\
    </ul>\
    ');

        var context = {collection: this.collection.toJSON()};
        $(this.el).html(template(context));
        $('#app').html(this.el);
        return this;
    }
});

某些情况下,在我第一次访问加载此视图的页面时,会显示5个项目(这是应该发生的)。但是,当我通过单击<span>10</span>来触发“setperpage”事件时,即使更新了URL并调用了fetch(),列表仍然不会更新。(我使用Firebug观察了请求,所以我知道我已经获得了包含10个项目的JSON响应)。为什么它们不重新渲染呢?我仍然只看到5个项目。

1个回答

12

this.collection.fetch();是异步的,因此调用render函数时仍会使用旧数据。

在调用render函数之前,您需要等待fetch()完成。

在initialize函数中,将render函数绑定到"reset"事件。

this.collection.on("reset", function() { this.render(); }, this);

当你需要新的数据时,请调用

this.collection.fetch({reset: true});

2
虽然你的前提是正确的,但是你的解决方案是错误的。如果你像那样绑定this.render,当this.render被调用时,this将会引用到错误的东西。你需要先赋值self=this,然后使用self.render - Jamie Wong
顺便说一句,也可以通过使用 this.collection.bind("refresh", (function(self) { return function() {self.render();}; }(this)); 来解决。不过你的解决方案可能更清晰明了。 - Jamie Wong
1
FYI,从版本0.5开始,此功能已更名为“重置”。我将相应地更新上面的解决方案。 - mhamrah
2
为了保留对this的引用,我会使用_.bind,或者更好地使用Backbone的Event.on,第三个参数是可选的上下文: this.collection.on("reset", function() { this.render(); }, this); - Cristi Mihai
为什么不这样写呢?this.collection.on( 'reset', this.render, this ); - ndequeker
在你的initialize方法中,最好使用'_.bindAll'而不是依赖于'self'或'that'引用。另外请注意,从1.0开始,你需要在fetch调用中传入'reset:true',否则这将无法工作。 - backdesk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接