1. 程式人生 > >Backbone入門指南(六):View (檢視)

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()方法,並將它作為最終渲染的入口方法。在團隊開發中,嚴格按照規範編碼可以幫助別人更好地理解和維護你的程式碼。

如果喜歡,點個贊,關注公眾號,我們將最好的內容分享與你!謝謝!