BackBone 教程 – 第 5 部分:理解 Backbone.js 集合






4.95/5 (23投票s)
如何使用 backbone.js 集合来操作一组模型,以及如何使用 RESTful API 轻松获取和保存集合。
引言
在本文中,我们将讨论 backbone.js 的集合(collections)。我们将了解如何使用集合来操作一组模型,以及如何使用 RESTful API 轻松获取和保存集合。
背景
每个应用程序都需要创建模型的集合,这些集合可以被排序、迭代,并在需要时进行筛选和搜索。考虑到这一点,Backbone 也提供了一种集合类型,使得处理模型集合变得相当简单直接。
完整系列链接
- BackBone 教程 – 第 1 部分:Backbone.Js 简介[^]
- BackBone 教程 – 第 2 部分:理解 Backbone 模型的基础知识[^]
- BackBone 教程 – 第 3 部分:关于 Backbone 模型的更多内容[^]
- BackBone 教程 – 第 4 部分:使用 HTTP REST 服务对 BackboneJs 模型进行 CRUD 操作[^]
- BackBone 教程 – 第 5 部分:理解 Backbone.js 集合[^]
- BackBone 教程 – 第 6 部分:理解 Backbone.js 视图[^]
- BackBone 教程 – 第 7 部分:理解 Backbone.js 路由和历史记录[^]
- BackBone 教程 – 第 8 部分:理解 Backbone.js 事件[^]
Using the Code
让我们开始详细了解 Backbone 集合。
创建一个集合
创建一个 Backbone 集合与创建一个模型类似。我们只需 extend
Backbone 的 collection 类来创建我们自己的集合。让我们继续使用之前的例子,我们创建了一个 Book
模型,现在让我们尝试创建一个简单的 BooksCollection
。
var BooksCollection = Backbone.Collection.extend({
});
这个集合将持有我们在之前文章中创建的 Book
模型。
var Book = Backbone.Model.extend({
defaults: {
ID: "",
BookName: ""
},
idAttribute: "ID",
urlRoot: 'https://:51377/api/Books'
});
为集合指定模型
要指定这个集合应该持有哪种模型,我们需要指定/覆盖 collection
类的 model
属性。
var BooksCollection = Backbone.Collection.extend({
model: Book,
});
一旦我们为 collection
指定了 model
属性,其内部会发生的事情是:每当我们创建这个 collection
时,它内部会创建一个指定模型的数组。然后,对这个 collection
对象的所有操作都会实际作用于那个数组。
实例化一个集合
可以使用 new
关键字来实例化一个 collection
。我们可以创建一个空的 collection
,然后稍后向其中添加 model
对象,或者在创建 collection
时传入一些 model
对象。
// Lets create an empty collection
var collection1 = new BooksCollection();
//Lets create a pre-populated collection
var book1 = new Book({ ID: 1, BookName: "Book 1" });
var book2 = new Book({ ID: 2, BookName: "Book 2" });
var collection2 = new BooksCollection([book1, book2]);
向集合中添加模型
要向 collection
添加一个项目,我们可以使用 collection
上的 add
方法。这里需要注意的重要一点是,如果具有相同 id
的项目已存在于 collection
中,add
操作将被忽略。
var book3 = new Book({ ID: 3, BookName: "Book 3" });
collection2.add(book3);
现在可能会有一种情况,我们实际上想要更新集合中一个已存在的模型。如果是这样,我们需要在 add
函数中传递 {merge: true}
选项。
var book3 = new Book({ ID: 3, BookName: "Book 3" });
collection2.add(book3);
var book3_changed = new Book({ ID: 3, BookName: "Changed Model" });
collection2.add(book3_changed, { merge: true });
另一个需要考虑的重点是,collection
保存的是实际模型的浅拷贝。因此,如果我们在将一个模型添加到 collection
后更改了它的属性,该属性值在 collection
内部也会发生改变。
此外,如果我们想添加多个模型,可以通过在 add
方法中传递一个模型数组来实现。
var book4 = new Book({ ID: 4, BookName: "Book 4" });
var book5 = new Book({ ID: 5, BookName: "Book 5" });
collection2.add([book4, book5]);
也可以在集合的特定索引处添加模型。要做到这一点,我们需要在 add
选项中传递 {at: location}
。
var book0 = new Book({ ID: 0, BookName: "Book 0" });
collection2.add(book0, {at:0});
注意:push
和 unshift
函数也可以用来向集合中添加模型。
从集合中移除模型
要从集合中移除模型,我们只需调用集合上的 remove
方法。remove
方法会简单地将该模型从集合中移除。
collection2.remove(book0);
此外,如果我们想清空模型,可以调用集合上的 reset
方法。
collection1.reset();
也可以通过在 reset
函数中传递一个模型数组来重置一个集合并用新的模型填充它。
collection2.reset([book4, book5]); // this will reset the collection and add book4 and book5 into it
注意:pop
和 shift
函数也可以用来从 collection
中移除 model
。
获取集合中的项目数量
可以使用 length
属性来获取集合中的项目总数。
var collection2 = new BooksCollection([book1, book2]);
console.log(collection2.length); // prints 2
从集合中检索模型
要从特定位置检索模型,我们可以使用 at
函数,并传递一个从 0
开始的索引。
var bookRecieved = collection2.at(3);
另外,要获取集合中已知模型的索引,我们可以使用 indexOf
方法。
var index = collection2.indexOf(bookRecieved);
如果我们知道模型的 id
或 cid
,我们也可以从集合中检索它。这可以通过使用 get
函数来完成。
var bookFetchedbyId = collection2.get(2); // get the book with ID=2
var bookFetchedbyCid = collection2.get("c3"); // get the book with cid=c3
如果我们想遍历集合中的所有模型,我们可以简单地使用经典的 for
循环,或者使用集合提供的 each
函数,它与 underscore.js 的 foreach
循环非常相似。
for (var i = 0; i < collection2.length; ++i) {
console.log(collection2.at(i).get("BookName"));
}
collection2.each(function (item, index, all) {
console.log(item.get("BookName"));
});
监听集合事件
当集合中的项目被添加、移除或更新时,Backbone collection
会触发事件。我们可以通过监听 add
、remove
和 change
事件来订阅这些事件。让我们在我们的模型中订阅这些事件,看看如何实现。
var BooksCollection = Backbone.Collection.extend({
model: Book,
initialize: function () {
// This will be called when an item is added. pushed or unshifted
this.on('add', function(model) {
console.log('something got added');
});
// This will be called when an item is removed, popped or shifted
this.on('remove', function(model) {
console.log('something got removed');
});
// This will be called when an item is updated
this.on('change', function(model) {
console.log('something got changed');
});
},
});
Set 函数
set
函数可用于更新一个集合中的所有项目。如果我们使用 set
函数,它会检查所有现有模型和传入 set
的模型。如果在传入的模型中发现任何新模型,它将被添加。如果有些模型不在新的模型列表中,它们将被移除。如果存在相同的模型,它们将被更新。
var collection3 = new BooksCollection();
collection3.add(book1);
collection3.add(book2);
collection3.add(book3);
collection3.set([book1, { ID: 3, BookName: "test sort"}, book5]);
上面显示的 set 函数将为 book2
调用 remove,为 book3
调用 change,为 book5
调用 add。
对集合进行排序
Backbone 会将 collection
中的所有模型保持在排序状态。我们可以调用 sort
函数来强制再次排序,但模型总是以排序后的顺序存储的。默认情况下,这些项目按照它们被添加到 collection
的顺序进行排序。但我们可以通过为我们的 collection
提供一个简单的比较器(comparator)来自定义这种排序行为。
var BooksCollection = Backbone.Collection.extend({
model: Book,
comparator: function (model) {
return model.get("ID");
},
});
这个比较器的作用是,通过指定应该用于排序的属性来覆盖默认的排序行为。我们甚至可以在这个比较器中使用自定义表达式。
使用 HTTP REST 服务获取集合
为了能够从服务器 fetch
(获取)collection
,我们需要为返回 collection
的 API 指定 url
。
var BooksCollection = Backbone.Collection.extend({
model: Book,
url: "https://:51377/api/Books",
});
现在,要从服务器 fetch
(获取)collection
,让我们调用 fetch
函数。
var collection4 = new BooksCollection();
collection4.fetch();
使用 HTTP REST 服务保存集合
让我们看看如何将集合中的项目保存到服务器上。
var collection4 = new BooksCollection();
collection4.fetch({
success: function (collection4, response) {
// fetch successful, lets iterate and update the values here
collection4.each(function (item, index, all) {
item.set("BookName", item.get("BookName") + "_updated"); // let's update all book names here
item.save();
});
}
});
在上面的代码中,我们对每个 model
对象调用了 save
。这可以通过覆盖 collection
上的 sync
函数,或者为 collection
创建一个包装器模型并使用它来保存数据,从而得到改进。
注意:Web API 代码可以从本系列的前一篇文章中下载。
关注点
在本文中,我们讨论了 Backbone 集合。本文是从初学者的角度撰写的。我希望它能提供有用的信息。
历史
- 2014年7月21日:初版