65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (17投票s)

2014 年 7 月 29 日

CPOL

8分钟阅读

viewsIcon

78793

downloadIcon

1251

在本文中,我们将尝试了解 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 可以被看作是

  1. 观察者,它们会一直监听 DOM 事件,并在事件触发时采取适当的行动。
  2. 由模型支持的对象,负责在屏幕上渲染模型数据。

让我们看看如何使用 backbone.js Views 来高效地管理应用程序。

完整系列链接

  1. BackBone 教程 – 第 1 部分:Backbone.Js 简介[^]
  2. BackBone 教程 – 第 2 部分:理解 Backbone Models 的基础知识[^]
  3. BackBone 教程 – 第 3 部分:更多关于 Backbone Models 的知识[^]
  4. BackBone 教程 – 第 4 部分:使用 HTTP REST 服务对 BackboneJs Models 进行 CRUD 操作[^]
  5. BackBone 教程 – 第 5 部分:理解 Backbone.js Collections[^]
  6. BackBone 教程 – 第 6 部分:理解 Backbone.js Views[^]
  7. BackBone 教程 – 第 7 部分:理解 Backbone.js Routes and History[^]
  8. 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 的方法

  1. 创建将与现有 DOM 元素关联的 view
  2. 创建将动态创建自己的 DOM 元素的 view

所以,让我们开始看看如何创建一个将与现有 DOM 元素关联的 View。Views 的构造函数能够接受很多参数。它可以接受 models、collections,甚至 View 应该与之关联的 DOM 元素。

假设我们要为现有 DOM 元素创建一个 View,即一个 ID 为 sampleDivdiv

var view1 = new sampleView({ el: $("#sampleDiv") });

当我们在应用程序运行时尝试查看 el 属性时,我们可以看到 el 属性包含 div 元素。

现在,让我们看看如何创建一个动态创建 DOM 元素的 View。其工作原理是,我们可以在 Backbone View 中指定 tagNameclassNameid 和 attributes。基于这些值,el 将由 Backbone 创建。让我们尝试使用这种方法创建一个带有 id 的简单 div

var sampleView2 = Backbone.View.extend({
    tagname: 'div',
    id: 'sampleDiv'
});

当我们创建这个 View 时,我们可以看到 view 与一个 div 相关联,该 div 是使用我们指定的 tagNameid 值创建的。

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 所做的是,它接受一个 bookcollection,并在 render 函数中,它使用 bookView 在关联的 el 中渲染书籍。接下来我们需要做的是将 HTML 页面上创建的 list 与此 View 关联作为其 el,并将 bookcollection 作为 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();
});

调用此 viewrender 函数将使用我们的 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 日:初版
© . All rights reserved.