Backbone.js更新集合中的模型
假设您正在使用Backbone.js构建Twitter克隆。 你有一些推文。 每条推文显然都是Tweet模型的一个实例。
您可以创建集合的实例,获取最新的10条推文,渲染它们并添加到DOM。
到现在为止还挺好。
如果你想在几分钟后打电话给服务器看看是否有新的推文怎么办? 如何将新到的推文添加到集合中?
如果使用fetch()
方法,则始终使用相同的URL。 没关系。 有没有一种聪明的方法可以使用Backbone / Underscore来过滤那些并将不在集合中的推文添加到集合中?
让我们假设你的每条推文都有一个唯一的标识符(如果没有,你应该创建一个)。
您可以构建您的后端,默认情况下,如果您在没有任何参数的情况下调用http://your.site.com/tweets,它会为您提供10条最新推文。
但是,如果你打电话给http://your.site.com/tweets?last_tweet_id=BLAblaBlA ,它会给你10条最新的推文,这些推文是你指定的last_tweet_id之后的。
您可以通过实现YourCollection.sync方法覆盖将数据从后端获取到Collection中的代码。
原因:Backbone.Collection首先尝试调用Collection.sync,如果未实现,则调用Backbone.sync函数,因此如果实现YourCollection.sync,将使用它。 以下是Backbone.Collection.fetch函数的片段:
(this.sync || Backbone.sync)('read', this, success, error);
所以你的同步会是这样的
var TweetCollection = Backbone.Collection.extend({ model: TweetModel, sync: function(method, collection, success, error) { var requestData={}; if(collection.length>0) { requestData.last_tweet_id=collection.last.id } var params = { url: "/tweet", type: "POST", data: requestData, success: success, error: error }; $.ajax(params); } }
您必须覆盖集合解析函数,以确保将响应附加到现有模型数组。
我不确定这是否可能在三月份,因为我最近才开始使用骨干网。 但更好的解决方案可能是将标准jQuery选项传递给Collection.fetch。
this.collection.fetch({data: {last_tweet: last_teet_id}});
查看jQuery文档以获取完整的参数列表。
我相信这就是你要找的东西:
yourCollection.fetch({add: true})
然后,您可以将集合视图的渲染绑定到add事件:
yourCollectionView.bind('add', this.render, this);
但是,如果渲染很重,你会想要延迟它以超时,以避免每次添加到集合时立即调用它:
yourCollectionView.bind('add', this.delayedRender, this); delayedRender: function() { var self = this; if (self.renderTimer) { clearTimeout(self.renderTimer); } self.renderTimer = setTimeout(function() { self.render(); self.renderTimer = null; }, 300); }
目前,开箱即用,没有。
我使用的技术如下。 你有你的TweetCollection扩展Backbone.Collection它有一个经典的RESTurl,如“/ tweets”。 您的后端仅发送10条最新记录(或第1页)。 要获得第2页,您将使用“/ tweets?page = 2”之类的url,后端会发送下10条推文。 问题是:在获取新记录时如何保留旧记录?
我使用2个集合:
- 第一个是用于在屏幕上呈现推文的那个。 这是一个正常的TweetCollection。
- 第二个是用于从服务器获取页面的那个。 我们称之为TweetPageCollection。
TweetPageCollection使用以下url扩展TweetCollection:
page: 1, url : function(){ return "/tweets?page=" + this.page; }
现在在您的控制器代码中,您可以执行以下操作:
initialize: function(){ this.tweets = new TweetCollection(); this.pages = new TweetPageCollection(); this.pages.bind("refresh", this.newPageReceived); this.pages.page = 1; this.pages.fetch(); this.tweet_list_view = new TweetListView({model: this.tweets}); }, getNextPage: function(){ this.pages.page++; this.pages.fetch(); }, newPageReceived : function(page){ // here you can check that the tweet is not already in the tweets collections this.tweets.add(page.toArray()); } ...
现在,当您想要获取新推文时,可以调用getNextPage(),当XHR成功时,您的视图将被刷新。
可以应用相同的原则来重新获取最新的推文。 2个集合,1个抓取,其他聚集提取。
我不认为这是一个骨干问题。 使用Twitter的RESTful API,您可以使用可选的since_id参数。 每次调用后,您的collections集可以保存已提取的最新推文的ID。 在您的urlfunction中使用此ID,您只会收到较新的推文。