`

Backbone入门指南(六):View (视图)

阅读更多

9. View (视图控制器)

  我们在前面的章节中介绍了Model和Collection,它们都是用于数据管理和交互,在本章我们讨论如何使用视图(View)将这些数据渲染到界面,以及如何管理界面事件和逻辑。

  Backbone中的视图提供了一组处理DOM事件、和渲染模型(或集合)数据的方法(在使用视图类之前,你必须先导入jQuery或Zepto)。

  视图类提供的方法非常简单,我们一般都会在Backbone.View的基础上进行扩展,但即使是特别复杂的视图类,它也应该仅仅是做界面事件、和渲染逻辑相关的操作,数据管理应该交由Model和Collection来完成,而业务逻辑应该由其它的类来完成。

9.1 定义和创建视图

  我们通过一段例子来说明如何创建View:

 

<div title="列表" style="color:red" id="list" class="listview"></div>
<script type="text/javascript">
    var ListView = Backbone.View.extend({
        el : '#list'
    });
    var listview = new ListView();
</script>
 

 

  在这个例子中,我们定义了一个ListView视图类,它继承自Backbone.View,我们通过new关键字实例化一个ListView对象。

  在定义ListView时,我们设置了el属性,它应该是一个字符串形式的DOM选择器,但视图对象在实例化时,会在内部通过这个选择器获取对应的DOM对象,并重新存放在el属性中。因此我们可以在视图的内部通过this.el来访问所关联的DOM对象。

  每个视图对象都会关联一个DOM 对象,视图中所有操作都限定在这个DOM对象之内,这样做可以便于视图界面的控制(如渲染、隐藏和移除等),同时能提高查找视图内子元素的效率。


  上面的例子中,id为list的标签是我们事先准备好的,在定义ListView时可以直接通过#list选择器来引用它,但实际开发时这些DOM可能是动态生成的,至少在定义视图类时它们还不存在。此时,我们可以通过另一种方式来设置视图的DOM对象:

 

<script type="text/javascript">
    var ListView = Backbone.View.extend({
        tagName : 'div',
        className : 'listview',
        id : 'list',
        attributes : {
            title : '列表',
            style : 'color:red'
        },
        render : function() {
            this.el.innerHTML = 'Hello World!';
            document.body.appendChild(this.el);
        }
    });
    var listview = new ListView();
    listview.render();
</script>
 

 

  运行这个例子,页面上输出了一段红色的文字:Hello World!。如果你通过Firebug等工具查看当前的DOM结构,你能看到</body>结束标签之前多了这样一段:

 

<div title="列表" style="color:red" id="list" class="listview">Hello World!</div>
 

 

  这段标签是视图对象在实例化时根据tagName、className、id和attributes属性自动创建的,结合我们的代码,你可以很清晰地看出:

 

  • tagName表示新标签的名称(如果没有设置,则默认为div标签)
  • className对应标签的class样式属性
  • id对应标签的id属性

 

  这3个是最常见的HTML属性,你可以在定义视图类时直接设置它们,如果还需要设置更多的属性,可以通过attributes属性来定义。

  你可能注意到,我们还定义了一个render()方法,在创建ListView实例之后,我们调用该方法将新建的标签添加到页面尾部,否则它只会存储在el属性中,而不会被显示。


  上面介绍的两种创建方式,是在两种不同的场景中使用,分别是对已经存在的DOM创建视图,和创建视图时同时创建新的DOM,因此你不应该不会同时使用到它们。

9.2 处理DOM事件

  视图很重要的一个特性是帮助我们自动绑定界面事件。回想一下我们以前是如何为界面标签绑定事件的?可能就像这样:

 

<p>
    <input type="button" value="Create" id="create" />
    <input type="button" value="Read" id="read" />
    <input type="button" value="Update" id="update" />
    <input type="button" value="Delete" id="delete" />
</p>
<script type="text/javascript">
    function createData() {
        // todo
    }
    function readData() {
        // todo
    }
    function updateData() {
        // todo
    }
    function deleteData() {
        // todo
    }

    $('#create').on('click', createData);
    $('#read').on('click', readData);
    $('#update').on('click', updateData);
    $('#delete').on('click', deleteData);
</script>
 

 

  这是一个典型的通过jQuery绑定DOM事件的例子,如果你正在开发或曾经开发过一些复杂的应用,你可能尝试过通过某种方式将这些代码更好的组织起来,以便使它们看起来结构更加清晰,更易维护。

  Backbone的视图对象为我们提供了事件的自动绑定机制,用于更好地维护DOM和事件间的关系,来看看下面的例子:

 

<p id="view">
    <input type="button" value="Create" id="create" />
    <input type="button" value="Read" id="read" />
    <input type="button" value="Update" id="update" />
    <input type="button" value="Delete" id="delete" />
</p>
<script type="text/javascript">
    var MyView = Backbone.View.extend({
        el : '#view',
        events : {
            'click #create' : 'createData',
            'click #read' : 'readData',
            'click #update' : 'updateData',
            'click #delete' : 'deleteData'
        },
        createData : function() {
            // todo
        },
        readData : function() {
            // todo
        },
        updateData : function() {
            // todo
        },
        deleteData : function() {
            // todo
        }
    });
    var view = new MyView();
</script>
 

 

  在这个例子中,我们将4个按钮放在一个id为view的标签中,并将这个标签与视图类MyView进行了关联。

  在定义视图类时,我们声明了一个events属性,它表示视图中的用户事件列表,描述方式如下:

  事件名称 选择器 : 事件处理函数

  事件名称可以是DOM对象支持的任何事件,选择器可以是jQuery或Zepto支持的任意选择器字符串(包括标签选择器、类选择器、id选择器等),而事件处理函数应该是已经定义在视图类本身的方法名称。

  视图对象会自动解析events列表中的描述,即使用jQuery或Zepto获取选择器描述的DOM对象,并将事件处理函数绑定到事件名称中。这些操作都会在视图类被实例化时自动完成,我们可以更关心视图类本身的结构,而不是刻意地去考虑如何绑定事件。


  你可能在担心另外一个问题:如果视图的DOM结构是动态生成的,Backbone是否提供了相应的方法用于动态绑定和解除事件?

  其实你并不需要关心这个问题,因为events中的事件是通过delegate()方法绑定到视图对象的el元素上,而并非是选择器所描述的元素。因此视图内的结构无论如何变化,events中的事件都是有效的。

  (如果你对jQuery比较熟悉,可能了解它所提供的delegate()方法。该方法实际上将事件绑定在父层元素,然后在事件冒泡过程中,通过检查目标子元素来触发事件。)

  视图对象通过delegate()方法绑定事件,意味着我们不需要关心视图结构变化对事件产生的影响,同时也说明events中选择器所对应的元素必须处于视图的el元素之内,否则绑定的事件是无法生效的。


  尽管如此,有些情况下可能我们仍然需要手动绑定和解除事件,视图对象提供了delegateEvents()和undelegateEvents()方法用于动态绑定和解除events事件列表,你可以通过查看API文档来了解它们。

9.3 渲染视图和数据

  我们之前提到,视图主要用于界面事件的绑定和数据渲染,然而视图对象仅仅提供了一个和渲染相关的方法render(),并且它是一个没有任何逻辑、也没有任何地方引用到的空方法,我们需要重载它来实现自己的渲染逻辑。

  视图中可能包含许多界面逻辑,这里建议所有的视图子类都重载render()方法,并将它作为最终渲染的入口方法。在团队开发中,严格按照规范编码可以帮助别人更好地理解和维护你的代码。

 

10
3
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics