BackBone 教程 – 第 6 部分:理解 Backbone.js Views






4.90/5 (17投票s)
在本文中,我们将尝试了解 Backbone.js 中的 View 类,并看看 View 类如何帮助我们轻松更新应用程序的相关部分。
引言
在本文中,我们将尝试了解 Backbone.js 中的 View 类,并看看 View 类如何帮助我们轻松更新应用程序的相关部分。
背景
编写 JavaScript 应用程序时最大的问题是处理意大利面条式代码,仅仅为了 HTML DOM 操作就需要编写大量的代码。UI 上的每个元素都需要在用户与之交互时执行某些操作。某些 UI 元素会希望根据新/更新的数据自动更新值。使用纯 HTML 和 JavaScript/jQuery 来完成所有这些工作是一个很大的问题(虽然可以做到,但简直是噩梦),尤其是在维护方面。
Backbone.js 的 View 在创建大型可管理应用程序时提供了极大的帮助。View 类更像是一种粘合剂,将 HTML 模板与 model
对象结合起来。此外,它还提供了机制来处理从 model
引发的事件,并更新 UI,处理 UI 事件并对其做出反应(对模型执行一些操作)。因此,从某种意义上说,我们可以说 View 只是监听模型和 UI 事件的观察者,这使它们成为处理所有事件并对其采取行动的理想场所。Backbone View 可以被看作是
- 观察者,它们会一直监听 DOM 事件,并在事件触发时采取适当的行动。
- 由模型支持的对象,负责在屏幕上渲染模型数据。
让我们看看如何使用 backbone.js Views 来高效地管理应用程序。
完整系列链接
- BackBone 教程 – 第 1 部分:Backbone.Js 简介[^]
- BackBone 教程 – 第 2 部分:理解 Backbone Models 的基础知识[^]
- BackBone 教程 – 第 3 部分:更多关于 Backbone Models 的知识[^]
- BackBone 教程 – 第 4 部分:使用 HTTP REST 服务对 BackboneJs Models 进行 CRUD 操作[^]
- BackBone 教程 – 第 5 部分:理解 Backbone.js Collections[^]
- BackBone 教程 – 第 6 部分:理解 Backbone.js Views[^]
- BackBone 教程 – 第 7 部分:理解 Backbone.js Routes and History[^]
- BackBone 教程 – 第 8 部分:理解 Backbone.js Events[^]
Using the Code
创建简单的 View
让我们从看看如何创建 Backbone Views 开始讨论。与 Backbone Models 和 Collections 一样,创建 Backbone View 也非常简单,只需继承 Backbone 中现有的 View
类即可。
var sampleView = Backbone.View.extend({
});
与 Models 和 Collections 一样,我们也可以重写 Backbone Views 的 initialize
和构造函数。让我们尝试看看如何重写 initialize
函数。
var sampleView = Backbone.View.extend({
initialize: function() {
console.log('sampleView has been created');
}
});
实例化 View 也非常直接。View 可以简单地使用 new
关键字来实例化。
var view1 = new sampleView();
将 Model 与 View 关联
每个 View 都将由一个 model
支持。这个 model
可以在构造函数中传递给 View。
var book1 = new Book({ ID: 1, BookName: "Book 1" });
var m_bookView = new bookView({model: book1});
这个 Model 可以是 Backbone Model,也可以是 Backbone Collection。View 可以从中提取信息并相应地渲染 HTML。
理解 el 属性
现在我们说 View 负责监听 DOM 元素的事件,也负责更新 DOM 元素。为了实现这一点,view
类应该与一个 DOM 元素关联/附加。Backbone Views 始终与一个 DOM 元素相关联。这个关联的 DOM 元素可以通过 el
属性进行访问/操作。
现在,有两种创建 view
的方法
- 创建将与现有 DOM 元素关联的
view
。 - 创建将动态创建自己的 DOM 元素的
view
。
所以,让我们开始看看如何创建一个将与现有 DOM 元素关联的 View。Views 的构造函数能够接受很多参数。它可以接受 models、collections,甚至 View 应该与之关联的 DOM 元素。
假设我们要为现有 DOM 元素创建一个 View,即一个 ID 为 sampleDiv
的 div
。
var view1 = new sampleView({ el: $("#sampleDiv") });
当我们在应用程序运行时尝试查看 el
属性时,我们可以看到 el
属性包含 div
元素。
现在,让我们看看如何创建一个动态创建 DOM 元素的 View。其工作原理是,我们可以在 Backbone View 中指定 tagName
、className
、id
和 attributes。基于这些值,el
将由 Backbone 创建。让我们尝试使用这种方法创建一个带有 id
的简单 div
。
var sampleView2 = Backbone.View.extend({
tagname: 'div',
id: 'sampleDiv'
});
当我们创建这个 View 时,我们可以看到 view
与一个 div
相关联,该 div
是使用我们指定的 tagName
和 id
值创建的。
var view2 = new sampleView2();
现在这两种方法在开发 Backbone 应用程序时提供了很大的灵活性。让我们通过一个简单的例子来理解整个画面。假设我们需要创建一本图书列表。我们知道这些项目应该渲染的区域,但实际项目将在运行时添加。这可以通过创建一个空列表并使用 JavaScript 在运行时添加列表项轻松实现。让我们看看如何使用 Backbone Views 来实现这一点。
首先,让我们创建一个简单的 View,它将图书数据渲染为列表项。为了做到这一点,我们将使用动态生成的 DOM 元素。
var bookView = Backbone.View.extend({
tagname: "li",
model: Book,
render: function (){
this.$el.html('<li>' + this.model.get("BookName") + '</li>');
return this;
}
});
这个 View 所做的是,它重写了 render
函数,将书名渲染为 list
元素。我们重写了 render
函数,将书渲染为列表项。
现在我们需要一个包含这些列表项的 View,即列表 View。为此,让我们在 HTML 中创建一个简单的 list
元素,然后使用这个 view
类来使用那个 el
。
var bookListView = Backbone.View.extend({
model: BooksCollection,
render: function() {
this.$el.html(); // lets render this view
var self = this;
for(var i = 0; i < this.model.length; ++i) {
// lets create a book view to render
var m_bookView = new bookView({model: this.model.at(i)});
// lets add this book view to this list view
this.$el.append(m_bookView.$el);
m_bookView.render(); // lets render the book
}
return this;
},
});
这个 view
所做的是,它接受一个 book
的 collection
,并在 render
函数中,它使用 bookView
在关联的 el
中渲染书籍。接下来我们需要做的是将 HTML 页面上创建的 list
与此 View 关联作为其 el
,并将 book
的 collection
作为 model
传递给此 view
。
var book1 = new Book({ ID: 1, BookName: "Book 1" });
var book2 = new Book({ ID: 2, BookName: "Book 2" });
var book3 = new Book({ ID: 3, BookName: "Book 3" });
var book4 = new Book({ ID: 4, BookName: "Book 4" });
var book5 = new Book({ ID: 5, BookName: "Book 5" });
var bookCollection = new BooksCollection([book1, book2, book3, book4, book5]);
var bookList = null;
$(document).ready(function () {
bookList = new bookListView({ el: $("#bookList"), model: bookCollection });
bookList.render();
});
调用此 view
的 render
函数将使用我们的 Backbone Views,并将图书列表渲染为无序列表。
注意:可以通过调用 View 的 setElement
方法随时更改 View 的 el
。
使用模板
现在,在我们的例子中,我们重写了 View 的 render
函数,并负责在我们自己的代码中渲染 HTML。这比纯 JavaScript/jquery 的方法要好,因为这里的 JavaScript 代码没有与 HTML 混合,并且 View 具有逻辑结构。
但问题是,我们的 View HTML 可能会变得非常复杂,并且不总是能够从我们的 render
函数中生成 HTML。为了缓解这个问题,Backbone 支持 View 模板。任何模板引擎都可以与 Backbone View 一起使用。为了理解模板的概念,让我们使用简单的 JavaScript 风格模板。
假设每本书都需要渲染为下拉菜单。这可以通过使用 bootstrap 非常轻松地实现。但是,在 render
函数中创建所有这些 HTML 可能不是一个好主意。所以,让我们创建另一组 View,它们将使用模板将书籍渲染到下拉菜单中。
var bookView2 = Backbone.View.extend({
model: Book,
tagName: 'li',
template: '',
initialize: function() {
this.template = _.template($('#bookItem').html());
},
render: function() {
this.$el.html(this.template(this.model.attributes));
return this;
}
});
var bookListView2 = Backbone.View.extend({
model: BooksCollection,
render: function() {
this.$el.html(); // lets render this view
for(var i = 0; i < this.model.length; ++i) {
// lets create a book view to render
var m_bookView = new bookView2({model: this.model.at(i)});
// lets add this book view to this list view
this.$el.append(m_bookView.$el);
m_bookView.render(); // lets render the book
}
return this;
},
});
模板定义在 HTML 文件本身中,如下所示:
<script type="text/template" id="bookItem">
<li role="presentation"><a role="menuitem" tabindex="-1" href="#"> <%= BookName %> </a></li>
</script>
这里会发生的是,bookView2
将使用此模板将书籍渲染为列表项。Backbone 可以使用任何 View 引擎。此外,这里使用的例子有点牵强,但使用这种方法也可以非常轻松地创建和渲染非常复杂的模板。
监听 DOM 事件
现在还剩一件重要的事情。view
对象如何监听 DOM 元素并执行所需的操作。为了理解这一点,让我们在列表 View 中添加一个简单的按钮,并尝试监听它的 click
操作。
var bookView2 = Backbone.View.extend({
model: Book,
tagName: 'li',
template: '',
events: {
'click': "itemClicked"
},
itemClicked: function () {
alert('clicked: ' + this.model.get('BookName'));
},
initialize: function() {
this.template = _.template($('#bookItem').html());
},
render: function() {
this.$el.html(this.template(this.model.attributes));
return this;
}
});
现在,每当 DOM 元素引发事件时,关联的 View 都会在 events 部分中查找其处理程序。如果处理程序存在,它将调用该处理程序。当我们想要监听 DOM 事件并采取一些操作时,这非常有用。我们可以使用 {"event selector": "callback"}
格式来声明我们的 DOM 事件处理程序。选择器是通常的 jquery/css 选择器。
监听 Model 更改
在大型应用程序中,可能有多个 View 渲染相同的数据。如果一个 View 更改了数据怎么办?其他 View 应该继续显示过时的数据吗?可能不应该。因此,我们也需要监听 Model 更改。这可以通过监听 Model 更改轻松实现,如下所示:
var bookListView = Backbone.View.extend({
model: BooksCollection,
initialize: function() {
// lets listen to model change and update ourselves
this.listenTo(this.model, "add", this.modelUpdated);
},
modelUpdated: function() {
this.render();
},
});
我们在这里所做的是,每当新的图书添加到 Collection 中时,关联的 View 都会监听 add
事件。接收到此事件后,它将简单地重新渲染 View。可以通过简单地向已渲染的 Collection 添加更多图书来测试这一点。
function AddMoreBooks() {
var i = bookCollection.length + 1;
var newBook = new Book({ID: i, BookName: 'yet another book_' + i});
bookCollection.add(newBook);
}
同样,我们也可以监听 change
事件来监听 model
更新。
var bookView = Backbone.View.extend({
tagName: "li",
model: Book,
initialize: function() {
// lets listen to model change and update ourselves
this.listenTo(this.model, "change", this.render);
}
});
为了测试这一点,让我们尝试更新屏幕上已渲染的一本书。
book1.set('BookName', book1.get('BookName') + '_updated');
从 DOM 中移除 View
可以通过调用 View 上的 remove
函数轻松地从 DOM 中移除 View。
bookList.remove();
看点
在本文中,我们探讨了 Backbone Views。我们了解了如何使用 Backbone Views 来实现结构更好的应用程序,这些应用程序可以轻松地执行 DOM 操作。
历史
- 2014 年 7 月 29 日:初版