javascript Backbone.js 更新集合中的模型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5427038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 17:10:20  来源:igfitidea点击:

Backbone.js updating of models in a collection

javascriptjquerybackbone.js

提问by Honza Pokorny

Let's say you are building a Twitter clone with Backbone.js. You have a collection of tweets. Each tweet is obviously an instance of the Tweet model.

假设您正在使用 Backbone.js 构建 Twitter 克隆。你有一组推文。每条推文显然都是 Tweet 模型的一个实例。

You create an instance of the collection, fetch the latest 10 tweets, render them and add to the DOM.

您创建集合的一个实例,获取最新的 10 条推文,渲染它们并添加到 DOM。

So far so good.

到现在为止还挺好。

What if you wanted to make a call to the server a few minutes later to see if any new tweets arrived? How can you add the newly arrived tweets to the collection?

如果您想在几分钟后调用服务器以查看是否有新推文到达怎么办?如何将新到达的推文添加到集合中?

If you use the fetch()method, you are hitting the same URL all the time. That's fine. Is there a clever way that I can use Backbone/Underscore to filter those and add the tweets that aren't in the collection to the collection?

如果您使用该fetch()方法,您将一直访问相同的 URL。没关系。有没有一种聪明的方法可以使用 Backbone/Underscore 来过滤它们并将不在集合中的推文添加到集合中?

回答by Vlad Gurovich

Lets assume that every one of your tweets has a unique identifier(if not, you should probably create one).

让我们假设你的每一条推文都有一个唯一的标识符(如果没有,你可能应该创建一个)。

You can structure your backend in such away that by default it gets you 10 latest tweets if you call http://your.site.com/tweetswithout any arguments.

您可以这样构建您的后端,默认情况下,如果您不带任何参数调用http://your.site.com/tweets,它会为您提供 10 条最新的推文。

If you however call http://your.site.com/tweets?last_tweet_id=BLAblaBlA, it will give you 10 latest tweets that came after the last_tweet_id that you specified.

但是,如果您调用http://your.site.com/tweets?last_tweet_id=BLABlaBlA,它将为您提供 10 条在您指定的 last_tweet_id 之后的最新推文。

You can override the code that gets the data from the backend into your Collection by implementing YourCollection.sync method.

您可以通过实现 YourCollection.sync 方法来覆盖从后端获取数据到您的集合的代码。

Reason: Backbone.Collection first tries to call Collection.sync and if its not implemented, it calls Backbone.sync function, so if you implement YourCollection.sync, it will be used. Here is the snippet from Backbone.Collection.fetch function:

原因:Backbone.Collection首先尝试调用Collection.sync,如果它没有实现,它会调用Backbone.sync函数,所以如果你实现了YourCollection.sync,它将被使用。这是 Backbone.Collection.fetch 函数的片段:

(this.sync || Backbone.sync)('read', this, success, error);

so your sync would be something like

所以你的同步会是这样的

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);
  }
}

You would have to override your collections parse function to make sure that the response is appended to the existing array of models.

您必须覆盖您的集合解析函数,以确保将响应附加到现有的模型数组。

回答by KenS

I'm not sure if this was possible back in March as I only recently started using backbone. But a better solution may be to pass standard jQuery options into Collection.fetch.

我不确定这在三月份是否可行,因为我最近才开始使用主干。但更好的解决方案可能是将标准 jQuery 选项传递到 Collection.fetch。

this.collection.fetch({data: {last_tweet: last_teet_id}});

Check out the jQuery documentation for a full list of parameters.

查看 jQuery 文档以获取完整的参数列表。

回答by Dave

I believe this is what you were looking for:

我相信这就是你要找的:

yourCollection.fetch({add: true})

Then, you can bind your collection view's render to the add event:

然后,您可以将集合视图的渲染绑定到添加事件:

yourCollectionView.bind('add', this.render, this);

Though, if the render is heavy, you'll want to delay it with a timeout to avoid immediately calling it for every addition to the collection:

但是,如果渲染很重,您将希望使用超时来延迟它,以避免在每次添加到集合时立即调用它:

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);
}

回答by Julien

Currently, out of the box, no.

目前,开箱即用,没有。

The technique I use is the following. You have your TweetCollection that extend Backbone.Collection and it has a classic REST url like "/tweets" . Your backend is sending only the 10 latest record (or page 1). To get page 2 you would use a url like "/tweets?page=2" and the backend would send the next 10 tweets. The question is really: how do you keep old record while fetching new one?

我使用的技术如下。你有你的 TweetCollection 扩展了 Backbone.Collection 并且它有一个经典的 REST url,比如 "/tweets" 。您的后端仅发送 10 条最新记录(或第 1 页)。要获得第 2 页,您将使用类似“/tweets?page=2”的 url,后端将发送接下来的 10 条推文。真正的问题是:如何在获取新记录的同时保留旧记录?

I use 2 collections:

我使用 2 个集合:

  • The first one is the one used to render the tweets on the screen. It is a normal TweetCollection.
  • The second one is the one used to get the pages from the server. Let's call it TweetPageCollection.
  • 第一个是用于在屏幕上呈现推文的。它是一个普通的 TweetCollection。
  • 第二个是用于从服务器获取页面的页面。我们称之为 TweetPageCollection。

TweetPageCollection extends TweetCollection with the following url:

TweetPageCollection 使用以下 URL 扩展 TweetCollection:

 page: 1,
 url : function(){ return "/tweets?page=" + this.page; }

Now in your controller code you can do something like this:

现在在您的控制器代码中,您可以执行以下操作:

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());
}
...

Now when you want to fetch new tweets, you call getNextPage() and when the XHR will succeed your view will be refreshed.

现在,当您想要获取新推文时,您可以调用 getNextPage() 并且当 XHR 成功时,您的视图将被刷新。

Same principles can be applied to refetch the latest tweets. 2 collections, 1 fetching, the other gathering fetches.

可以应用相同的原则来重新获取最新的推文。2 个集合,1 个取物,另一个收集取物。

回答by Denny

I don't think this is a backbone issue. Using Twitter's RESTful API you can use the optional since_id parameter. After each call your collection could save the id of the most recent tweet it has fetched. Use this id in your url function and you'll only receive newer tweets.

我不认为这是一个骨干问题。使用 Twitter 的 RESTful API,您可以使用可选的 since_id 参数。每次调用后,您的集合可以保存它获取的最新推文的 ID。在您的 url 函数中使用此 ID,您将只会收到较新的推文。