Backbone.js:区分仍在加载的集合和空集合?

时间:2012-10-10 02:03:27

标签: javascript backbone.js

使用Backbone.js,我有一个我实例化的集合,X。实例化后,我立即调用X.fetch(),以便尽快从服务器加载数据。然后,我将X传递给将对集合进行操作的各种视图。

这些视图的最佳方法是区分何时集合只是加载(因此为空)以及何时加载但实际上是空的?我想我的观点显示适当的“加载...”文本,直到该集合已经ping通服务器。在这一点上,我希望他们说“看起来这里什么都没有。也许你应该添加一些东西。”

我在考虑在每个视图中收听集合上的reset事件,但这对我来说似乎相当脆弱。如果在视图附加其侦听器之前已经触发重置事件,会发生什么?是否有一个很好的模式来检查集合的状态,以确定它是否被取出?

2 个答案:

答案 0 :(得分:3)

fetch方法基于AJAX的异步性质是异步的。 因此,您需要实现事件驱动的行为。

X.fetch({
    success: function(collection, response) {
        hidePreLoader();
        renderViews(collection); // collection argument is your X collection.
    }
});

<强>更新

根据您对我的回答的评论,我可以提出另一个想法。 即你可以设置

X.isLoaded = true;

或任何其他属性,如

X.loadedAt = Date.now();

success回调中,因此其他代码可以检查此属性的状态。

但是我在这里看到了一种糟糕的设计。 您可以使用preloader显示您的视图,并在success回调触发器中,您的视图将开始与集合一起使用,因为它已加载并准备使用。 总的来说,我再次建议你使用事件驱动的行为。

我没有测试,但这是我的想法的代表:

var XCollection = Backbone.Collection.extend({

    // ...

    model: X,
    loadState: {},
    loadedAt: -1,
    initialize: function(options) {
        _.extend(this.loadState, Backbone.Events);
    },

    isLoaded: function() {
        return this.loadedAt > -1;
    }
});

var Subview = Backbone.View.extend({

    // ...

    initialize: function(options) {
        this.collection.loadState.on("loadComplete",
            this.onLoadComplete, this);
    },

    onLoadComplete: function(response) {
        this.hidePreloader();
        this.renderData();
    },

    /**
     * Checks is the collection loaded and view can render fetched models.
     * It's just an example.
     * You'll not need to use it if you're handling a loadComplete event.
     */
    isRenderingAllowed: function() {
        return this.collection.isLoaded();
    }
});

var XView = Subview.extend({

    // ...

    initialize: function(options) {
        Subview.prototype.initialize.apply(this, arguments);
    }
});

var YView = Subview.extend({

    // ...

    initialize: function(options) {
        Subview.prototype.initialize.apply(this, arguments);
    }
});


// ...

var x = new XCollection();

var xView = new XView({collection: x}),
    yView = new YView({collection: x});

x.fetch({
    success: function(collection, response) {
        collection.loadedAt = Date.now();
        collection.loadState.trigger("loadComplete", response);
    }
});

Documentation

答案 1 :(得分:1)

确保在致电fetch()之前初始化视图。这样您就可以监听reset事件,并确保所有视图都已更新。如果你想尽快加载xlist,最好将它引导到你的html服务器端。

这样做的方法可能是:

<script src="/public/js/collecions/x-list.js">
<script src="/public/js/views/x-view.js">

    <script>
         var xlist = new App.Collections.XList();

        _.each($(".xdiv"), function(el){
             new App.Views.XView({
                 el: el,
                 collection: xlist
             });
             // make sure that XView have this in it's initialize method:
             // this.collection.bind("reset", this.render, this)
        }

        xlist.fetch();

        // or even better, use bootstraped data:

        x.list.reset((<%= @data.to_json %>)
    </script>