Backbone

第一章 Hello Backbonejs

1.1 基礎概念

Backbone,英文意思是:勇氣, 脊骨,可是在程序裏面,尤爲是在Backbone後面加上後綴js以後,它就變成了一個框架,一個js庫。javascript

Backbone.js,不知道做者是以什麼樣的目的來對其命名的,多是但願這個庫會成爲web端開發中脊樑骨。html

好了,八卦完了開始正題。前端

Backbone.js提供了一套web開發的框架,經過Models進行key-value綁定及自定義事件處理,經過Collections提供一套豐富的API用於枚舉功能,經過Views來進行事件處理及與現有的Application經過RESTful JSON接口進行交互.它是基於jQuery和underscore的一個前端js框架。java

總體上來講,Backbone.js是一個web端javascript的MVC框架,算是輕量級的框架。它能讓你像寫Java(後端)代碼組織js代碼,定義類,類的屬性以及方法。更重要的是它可以優雅的把本來無邏輯的javascript代碼進行組織,而且提供數據和邏輯相互分離的方法,減小代碼開發過程當中的數據和邏輯混亂。python

在Backbonejs有幾個重要的概念,先介紹一下:Model,Collection,View,Router。其中Model是根據現實數據創建的抽象,好比人(People);Collection是Model的一個集合,好比一羣人;View是對Model和Collection中數據的展現,把數據渲染(Render)到頁面上;Router是對路由的處理,就像傳統網站經過url現實不一樣的頁面,在單頁面應用(SPA)中經過Router來控制前面說的View的展現。jquery

經過Backbone,你能夠把你的數據看成Models,經過Models你能夠建立數據,進行數據驗證,銷燬或者保存到服務器上。當界面上的操做引發model中屬性的變化時,model會觸發change的事件。那些用來顯示model狀態的views會接受到model觸發change的消息,進而發出對應的響應,而且從新渲染新的數據到界面。在一個完整的Backbone應用中,你不須要寫那些膠水代碼來從DOM中經過特殊的id來獲取節點,或者手工的更新HTML頁面,由於在model發生變化時,views會很簡單的進行自我更新。git

上面是一個簡單的介紹,關於backbone我看完他的介紹和簡單的教程以後,第一印象是它爲前端開發制定了一套本身的規則,在這個規則下,咱們能夠像使用django組織python代碼同樣的組織js代碼,它很優雅,可以使前端和server的交互變得簡單。github

在查backbone資料的時候,發現沒有很系統的中文入門資料和更多的實例,因此我打算本身邊學邊實踐邊寫,爭取能讓你們經過一系列文章能快速的用上Backbone.js。web

關於backbone的更多介紹參看這個:數據庫

http://documentcloud.github.com/backbone/

http://backbonetutorials.com/

1.2 backbone的應用範圍:

它雖然是輕量級框架,可是框架這東西也不是隨便什麼地方都能用的,否則就會出現殺雞用牛刀,費力不討好的結果。那麼適用在哪些地方呢?

根據個人理解,以及Backbone的功能,若是單個網頁上有很是複雜的業務邏輯,那麼用它很合適,它能夠很容易的操做DOM和組織js代碼。

豆瓣的阿爾法城是一個極好的例子——純單頁、複雜的前端邏輯。

固然,除了我本身分析的應用範圍以外,在Backbone的文檔上看到了不少使用它的外國站點,有不少,說明Backbonejs仍是很易用的。

稍稍列一下國內用到Backbonejs的站點:

1. 豆瓣阿爾法城 連接:http://alphatown.com/

2. 豆瓣閱讀 連接:http://read.douban.com/ 主要用在圖書的正文頁

3. 百度開發者中心 連接:http://developer.baidu.com/

4. 手機搜狐直播間 連接:http://zhibo.m.sohu.com/

5. OATOS企業網盤 連接:http://app.oatos.com

1.3 學以至用

如今,咱們就要開始學習Backbonejs了,我假設你沒有看過個人初版,那一版有不少不少問題,在博客上也有不少人反饋。可是若是你把那一版看明白了,這新版的教程你能夠粗略的瀏覽一遍,不事後面新補充的實踐是要本身寫出來、跑起來的。

先說咱們爲何要學習這新的東西呢?簡單說來是爲了掌握更加先進的工具。那爲何要掌握先進的工具呢?簡單來講就是爲了讓咱們可以以更合理、優雅的方式完成工做,反應到代碼上就是讓代碼變得可維護,易擴展。若是從複雜的方向來講的話,這倆話題都夠我寫好幾天的博客了。

學以至用,最直接有效的就是用起來,光學是沒用的,尤爲是編程這樣的實踐科學。新手最常犯的一個錯誤就是喜歡不停的去看書,看過了就覺得會了,而後就開始瘋狂的學下一本。卻不知看懂和寫出來能運行是兩種徹底不一樣的狀態。所以建議新手——編程新手仍是踏踏實實的把代碼都敲了,執行了,成功了纔是。

下面直接給一個簡單的Demo出來,用到了Backbonejs的三個主要模塊:Views,Collection,Model。經過執行這個例子,瞭解這個例子的運行過程,快速對要作的東西有一個感受,而後再逐步擊破。

1.4 完整DEMO

這個demo的主要功能是點擊頁面上得「新手報到」按鈕,彈出對話框,輸入內容以後,把內容拼上固定的字符串顯示到頁面上。事件觸發的邏輯是: click 觸發checkIn方法,而後checkIn構造World對象放到已經初始化worlds這個collection中。

來看完整的代碼:

<!DOCTYPE html>
<html>
<head>
    <title>the5fire.com-backbone.js-Hello World</title>
</head>
<body>
    <button id="check">新手報到</button>
    <ul id="world-list">
    </ul>
    <a href="http://www.the5fire.com">更多教程</a>    <script src="http://the5fireblog.b0.upaiyun.com/staticfile/jquery-1.10.2.js"></script>    <script src="http://the5fireblog.b0.upaiyun.com/staticfile/underscore.js"></script>    <script src="http://the5fireblog.b0.upaiyun.com/staticfile/backbone.js"></script>    <script>    (function ($) {        World = Backbone.Model.extend({            //建立一個World的對象,擁有name屬性            name: null        });        Worlds = Backbone.Collection.extend({            //World對象的集合            initialize: function (models, options) {                    this.bind("add", options.view.addOneWorld);            }        });        AppView = Backbone.View.extend({            el: $("body"),            initialize: function () {                //構造函數,實例化一個World集合類                //而且以字典方式傳入AppView的對象                this.worlds = new Worlds(null, { view : this })            },            events: {                //事件綁定,綁定Dom中id爲check的元素                "click #check":  "checkIn",            },            checkIn: function () {                var world_name = prompt("請問,您是哪星人?");                if(world_name == "") world_name = '未知';                var world = new World({ name: world_name });                this.worlds.add(world);            },            addOneWorld: function(model) {                $("#world-list").append("<li>這裏是來自 <b>" + model.get('name') + "</b> 星球的問候:hello world!</li>");            }        });        //實例化AppView        var appview = new AppView;    })(jQuery);    </script></body>
</html>

這裏面涉及到backbone的三個部分,View、Model、Collection,其中Model表明一個數據模型,Collection是模型的一個集合,而View是用來處理頁面以及簡單的頁面邏輯的。

動手把代碼放到你的編輯器中吧,成功執行,而後修改某個地方,再次嘗試。

第二章 Backbonejs中的Model實踐

上一章主要是經過簡單的代碼對Backbonejs作了一個歸納的展現,這一章開始從Model層提及,詳細解釋Backbonejs中的Model這個東西。

對於Model這一部分,其官網是這麼說的:「Model是js應用的核心,包括基礎的數據以及圍繞着這些數據的邏輯:數據轉換、驗證、屬性計算和訪問控制」。這句話基本上高度歸納了Model在一個項目中的做用。實際上,不只僅是js應用,在任何以數據收集和處理的項目中Model都是很重要的一塊內容。

Model這個概念在個人印象中是來自於MVC這個東西,Model在其中的做用,除了是對業務中實體對象的抽象,另外的做用就是作持久化,所謂持久化就是把數據存儲到磁盤上——文件形式、數據庫形式。在web端也有對應的操做,好比存入LocalStorage,或者Cookie。

在web端,Model還有一個重要的功能就是和服務器端進行數據交互,就像是服務器端的程序須要和數據庫交互同樣。所以Model應該是攜帶數據流竄於各個模塊之間的東西。

下面讓咱們經過一個一個的實例來逐步瞭解Model。

先定義一個頁面結構,實踐時須在註釋的地方填上各小節的代碼

<!DOCTYPE html>
<html>
<head>
<title>the5fire-backbone-model</title>
</head>
<body>
</body>
<script src="http://the5fireblog.b0.upaiyun.com/staticfile/jquery-1.10.2.js"></script>
<script src="http://the5fireblog.b0.upaiyun.com/staticfile/underscore.js"></script>
<script src="http://the5fireblog.b0.upaiyun.com/staticfile/backbone.js"></script><script>(function ($) {    /**    *此處填充代碼下面練習代碼    **/})(jQuery);</script></html>

2.1 最簡單的對象

var Man = Backbone.Model.extend({    initialize: function(){        alert('Hey, you create me!');
    }
});var man = new Man;

這個確實很簡單了,只是定義了一個最基礎的Model,只是實現了initialize這個初始化方法,也稱構造函數。這個函數會在Model被實例化時調用。

2.2 對象屬性賦值的兩種方法

第一種,直接定義,設置默認值。

var Man = Backbone.Model.extend({    initialize: function(){        alert('Hey, you create me!');
    },
    defaults: {
        name:'張三',
        age: '38'
    }
});var man = new Man;alert(man.get('name'));

第二種,賦值時定義

var Man = Backbone.Model.extend({    initialize: function(){        alert('Hey, you create me!');
    }
});var man = new Man;
man.set({name:'the5fire',age:'10'});alert(man.get('name'));

從這個對象的取值方式能夠知道,屬性在一個Model是以字典(或者相似字典)的方式存在的,第一種設定默認值的方式,只不過是實現了Backbone的defaults這個方法,或者是給defaults進行了賦值。

2.3 對象中的方法

var Man = Backbone.Model.extend({    initialize: function(){        alert('Hey, you create me!');
    },
    defaults: {
        name:'張三',
        age: '38'
    },    aboutMe: function(){        return '我叫' + this.get('name') + ',今年' + this.get('age') + '歲';
    }
});var man = new Man;alert(man.aboutMe());

也是比較簡單,只是增長了一個新的屬性,值是一個function。說到這,不知道你是否發現,在全部的定義或者賦值操做中,都是經過字典的方式來完成的,好比extend Backbone的Model,以及定義方法,定義默認值。方法的調用和其餘的語言同樣,直接 . 便可,參數的定義和傳遞也同樣。

2.4 監聽對象中屬性的變化

假設你有在對象的某個屬性發生變化時去處理一些業務的話,下面的示例會有幫助。依然是定義那個類,不一樣的是咱們在構造函數中綁定了name屬性的change事件。這樣當name發生變化時,就會觸發這個function。

var Man = Backbone.Model.extend({    initialize: function(){        alert('Hey, you create me!');        //初始化時綁定監聽
        this.bind("change:name",function(){            var name = this.get("name");            alert("你改變了name屬性爲:" + name);
        });
    },
    defaults: {
        name:'張三',
        age: '38'
    },    aboutMe: function(){        return '我叫' + this.get('name') + ',今年' + this.get('age') + '歲';
    }
});var man = new Man;//觸發綁定的change事件,alert。man.set({name:'the5fire'});//觸發綁定的change事件,alert。man.set({name:'the5fire.com'});

2.5 爲對象添加驗證規則,以及錯誤提示

var Man = Backbone.Model.extend({    initialize: function(){        alert('Hey, you create me!');        //初始化時綁定監聽, change事件會先於validate發生
        this.bind("change:name",function(){            var name = this.get("name");            alert("你改變了name屬性爲:" + name);
        });        this.bind("invalid",function(model,error){            alert(error);
        });
    },
    defaults: {
        name:'張三',
        age: '38'
    },    validate:function(attributes){        if(attributes.name == '') {            return "name不能爲空!";
        }
    },    aboutMe: function(){        return '我叫' + this.get('name') + ',今年' + this.get('age') + '歲';
    }
});var man = new Man;// 這種方式添加錯誤處理也行// man.on('invalid', function(model, error){//         alert(error);// });//默認set時不進行驗證man.set({name:''});//手動觸發驗證, set時會觸發//man.set({name:''}, {'validate':true});//save時觸發驗證。根據驗證規則,彈出錯誤提示。man.save();

2.6 和服務器進行交互,對象的保存和獲取

首先須要聲明的是,這個例子須要後端配合,能夠在 code 目錄中找到對應的py文件,須要webpy和mako這兩個庫。 這裏須要爲對象定義一個url屬性,調用save方法時會post對象的全部屬性到server端,調用fetch方法是又會發送get請求到server端。接受數據和發送數據均爲json格式:

var Man = Backbone.Model.extend({
    url:'/man/',    initialize: function(){        alert('Hey, you create me!');        //初始化時綁定監聽
        this.bind("change:name",function(){            var name = this.get("name");            alert("你改變了name屬性爲:" + name);
        });        this.bind("error",function(model,error){            alert(error);
        });
    },
    defaults: {
        name:'張三',
        age: '38'
    },    validate:function(attributes){        if(attributes.name == '') {            return "name不能爲空!";
        }
    },    aboutMe: function(){        return '我叫' + this.get('name') + ',今年' + this.get('age') + '歲';
    }
});var man = new Man;;
man.set({name:'the5fire'});//會發送POST到模型對應的url,數據格式爲json{"name":"the5fire","age":38}man.save();//而後接着就是從服務器端獲取數據使用方法fetch([options])var man1 = new Man;//第一種狀況,若是直接使用fetch方法,//那麼他會發送get請求到你model的url中,//你在服務器端能夠經過判斷是get仍是post來進行對應的操做。man1.fetch();//第二種狀況,在fetch中加入參數,以下:man1.fetch({url:'/man/'});//這樣,就會發送get請求到/getmans/這個url中,//服務器返回的結果樣式應該是對應的json格式數據,同save時POST過去的格式。//不過接受服務器端返回的數據方法是這樣的:man1.fetch({url:'/man/',    success:function(model,response){        alert('success');        //model爲獲取到的數據
        alert(model.get('name'));
    },error:function(){        //當返回格式不正確或者是非json數據時,會執行此方法
        alert('error');
    }
});

還有一點值得一提的是關於url和urlRoot的事情了,若是你設置了url,那麼你的CRUD都會發送對應請求到這個url上,可是這樣有一個問題,就是delete請求,發送了請求,可是卻沒有發送任何數據,那麼你在服務器端就不知道應該刪除哪一個對象(記錄),因此這裏又一個urlRoot的概念,你設置了urlRoot以後,你發送PUT和DELETE請求的時候,其請求的url地址就是:/baseurl/[model.id],這樣你就能夠在服務器端經過對url後面值的提取更新或者刪除對應的對象(記錄)

補充一點,就是關於服務器的異步操做都是經過Backbone.sync這個方法來完成的,調用這個方法的時候會自動的傳遞一個參數過去,根據參數向服務器端發送對應的請求。好比你save,backbone會判斷你的這個對象是否是新的,若是是新建立的則參數爲create,若是是已存在的對象只是進行了改變,那麼參數就爲update,若是你調用fetch方法,那參數就是read,若是是destory,那麼參數就是delete。也就是所謂的CRUD ("create", "read", "update", or "delete"),而這四種參數對應的請求類型爲POST,GET,PUT,DELETE。你能夠在服務器根據這個request類型,來作出相應的CRUD操做。

關於Backbone.sync在後面會有如何自定義這一部分的章節。

上面服務器端的代碼在 code 下能夠找到,基於webpy和mako的。

第三章 Backbonejs中的Collections實踐

上一節介紹了model的使用,model算是對現實中某一物體的抽象,好比你能夠定義一本書的model,具備書名(title)還有書頁(page_num)等屬性。僅僅用一個Model是不足以呈現現實世界的內容,所以基於Model,這節咱們來看collection。collection是model對象的一個有序的集合,也能夠理解爲是model的容器。概念理解起來十分簡單,在經過幾個例子來看一下,會以爲更容易理解。

3.1 關於book和bookshelf的例子

var Book = Backbone.Model.extend({

    defaults : {
        title:'default'
    },    initialize: function(){        //alert('Hey, you create me!');
    }

});var BookShelf = Backbone.Collection.extend({
    model : Book
});var book1 = new Book({title : 'book1'});var book2 = new Book({title : 'book2'});var book3 = new Book({title : 'book3'});//注意這裏面是數組,或者使用add//var bookShelf = new BookShelf([book1, book2, book3]);var bookShelf = new BookShelf;

bookShelf.add(book1);
bookShelf.add(book2);
bookShelf.add(book3);
bookShelf.remove(book3);//基於underscore這個js庫,還可使用each的方法獲取collection中的數據bookShelf.each(function(book){    alert(book.get('title'));
});

很容易理解吧。

3.2 使用fetch從服務器端獲取數據

首先要在上面的的Bookshelf中定義url,注意collection中並無urlRoot這個屬性。或者你直接在fetch方法中定義url的值,以下:

//注意這裏bookShelf.url = '/books/';
bookShelf.fetch({    success:function(collection, response, options){
        collection.each(function(book){            alert(book.get('title'));
        });
    },error:function(collection, response, options){        alert('error');
    }
});

其中也定義了兩個接受返回值的方法,具體含義我想很容易理解,返回正確格式(json)的數據,就會調用success方法,錯誤格式的數據就會調用error方法,固然error方法也看添加和success方法同樣的形參。

對應的BookShelf的返回格式以下:[{'title':'book0'},{'title':'book1'}.....]

3.3 reset方法

使用這個方法的時候是要和上面的fetch進行配合的,collection在fetch到數據以後,默認狀況會調用set方法(set方法向collection裏面添加新model,若是該model以前存在則會合並,與此同時會觸發collection的add事件),能夠經過參數{reset: true}來手動觸發reset,reset會整個清空collection從新添加全部model。這時你就須要在collection中定義reset方法或者是綁定reset方法。這裏使用綁定演示:

var showAllBooks = function(){
    bookShelf.each(function(book){        //將book數據渲染到頁面的操做。
        document.writeln(book.get('title'));
    });
}

bookShelf.bind('reset',showAllBooks);
bookShelf.url = '/books/'; //注意這裏bookShelf.fetch({    // 須要主動傳遞reset,纔會觸發reset
    reset: true,    success:function(collection, response, options){
        collection.each(function(book){            alert(book.get('title'));
        });
    },error:function(collection, response, options){        alert('error');
    }
});

綁定的步驟要在fetch以前進行。

3.4 發送數據到Server端

建立數據,其實就是調用collection的create方法,POST對應的Model對象(json數據)到配置好的url上。以後會返回一個model的實例,以下面代碼中的onebook。

var NewBooks = Backbone.Collection.extend({
    model: Book,
    url: '/books/'});var books = new NewBooks;var onebook = books.create({
    title: "I'm coming",
});

完整代碼能夠在 code 中找到, 服務器端的代碼後面會介紹。

第四章 Backbonejs中的Router實踐

前面介紹了Model和Collection,基本上屬於程序中靜態的數據部分。這一節介紹Backbone中的router,屬於動態的部分,見名知意,router——路由的意思,顯然是可以控制url指向哪一個函數的。具體是怎麼作的一會經過幾個實例來看看。

在如今的單頁應用中,全部的操做、內容都在一個頁面上呈現,這意味着瀏覽器的url始終要定位到當前頁面。那麼一個頁面中的左右的操做總不能都經過事件監聽來完成,尤爲是對於須要切換頁面的場景以及須要分享、收藏固定連接的狀況。所以就有了router,經過hash的方式(即#page)來完成。不過隨着瀏覽器發展,大多數的瀏覽器已經能夠經過history api來操控url的改變,能夠直接使用 /page 來完成以前須要hash來完成的操做,這種方式看起來更爲直觀一些。下面提供過幾個demo來切實體會一番。

4.1 一個簡單的例子

var AppRouter = Backbone.Router.extend({
    routes: {        "*actions" : "defaultRoute"
    },    defaultRoute : function(actions){        alert(actions);
    }
});var app_router = new AppRouter;

Backbone.history.start();

須要經過調用Backbone.history.start()方法來初始化這個Router。

在頁面上須要有這樣的a標籤:

<a href="#actions">testActions</a>

點擊該連接時,便會觸發defaultRouter這個方法。

4.2 這個routes映射要怎麼傳參數

看下面例子,立馬你就知道了

var AppRouter = Backbone.Router.extend({

    routes: {        "posts/:id" : "getPost",        "*actions" : "defaultRoute"
    },    getPost: function(id) {        alert(id);
    },    defaultRoute : function(actions){        alert(actions);
    }
});var app_router = new AppRouter;
Backbone.history.start();

對應的頁面上應該有一個超連接:

<a href="#/posts/120">Post 120</a>

從上面已經能夠看到匹配#標籤以後內容的方法,有兩種:一種是用「:」來把#後面的對應的位置做爲參數;還有一種是「*」,它能夠匹配全部的url,下面再來演練一下。

var AppRouter = Backbone.Router.extend({

    routes: {        "posts/:id" : "getPost",        //下面對應的連接爲<a href="#/download/user/images/hey.gif">download gif</a>
        "download/*path": "downloadFile",        //下面對應的連接爲<a href="#/dashboard/graph">Load Route/Action View</a>
        ":route/:action": "loadView",        "*actions" : "defaultRoute"
    },    getPost: function(id) {        alert(id);
    },    defaultRoute : function(actions){        alert(actions);
    },    downloadFile: function( path ){        alert(path); // user/images/hey.gif
    },    loadView: function( route, action ){        alert(route + "_" + action); // dashboard_graph
    }

});var app_router = new AppRouter;
Backbone.history.start();

4.3 手動觸發router

上面的例子都是經過頁面點擊觸發router到對應的方法上,在實際的使用中,還存在一種場景就是須要在某一個邏輯中觸發某一個事件,就像是jQuery中得trigger同樣,下面的代碼展現怎麼手動觸發router。

routes: {    "posts/:id" : "getPost",    "manual": "manual",    "*actions": "defaultRoute",
},// 省略部分代碼loadView: function( route, action ){    alert(route + "_" + action); // dashboard_graph},manual: function() {    alert("call manual");
    app_router.navigate("/posts/" + 404, {trigger: true, replace: true});
}

對應着在頁面添加一個a標籤: <a href="#/manual">manual</a> 而後點擊這個連接,便會觸發posts/:id對應的方法。

這裏須要解釋的是navigate後面的兩個參數。trigger表示觸發事件,若是爲false,則只是url變化,並不會觸發事件,replace表示url替換,而不是前進到這個url,意味着啓用該參數,瀏覽器的history不會記錄這個變更。

完整代碼依然在 code 中能夠找到。

第五章 Backbonejs中的View實踐

前面介紹了存放數據的Model和Collection以及對用戶行爲進行路由分發的Router(針對連接)。這一節終於能夠往頁面上放點東西來玩玩了。這節就介紹了Backbone中得View這個模塊。Backbone的View是用來顯示你的model中的數據到頁面的,同時它也可用來監聽DOM上的事件而後作出響應。可是這裏要提一句的是,相比於Angularjs中model變化以後頁面數據自動變化的特性,Backbone要手動來處理。至於這兩種方式的對比,各有優劣,能夠暫時不關心。

下面依然是經過幾個示例來介紹下view的功能,首先給出頁面的基本模板:

<!DOCTYPE html>
<html>
<head>
    <title>the5fire-backbone-view</title>
</head>
<body>
    <div id="search_container"></div>

    <script type="text/template" id="search_template">
        <label><%= search_label %></label>
        <input type="text" id="search_input" />
        <input type="button" id="search_button" value="Search" />
    </script>
<script src="http://the5fireblog.b0.upaiyun.com/staticfile/jquery-1.10.2.js"></script>
<script src="http://the5fireblog.b0.upaiyun.com/staticfile/underscore-min.1.8.2.js"></script>
<script src="http://the5fireblog.b0.upaiyun.com/staticfile/backbone.js"></script><script>(function ($) {    //此處添加下面的試驗代碼})(jQuery);</script></body>
</html>

5.1 一個簡單的view

var SearchView = Backbone.View.extend({    initialize: function(){        alert('init a SearchView');
    }
});var searchView = new SearchView();

是否是以爲很沒有技術含量,全部的模塊定義都同樣。

5.2 el屬性

這個屬性用來引用DOM中的某個元素,每個Backbone的view都會有這麼個屬性,若是沒有顯示聲明,Backbone會默認的構造一個,表示一個空的div元素。el標籤能夠在定義view的時候在屬性中聲明,也能夠在實例化view的時候經過參數傳遞。

var SearchView = Backbone.View.extend({    initialize: function(){        alert('init a SearchView');
    }
});var searchView = new SearchView({el: $("#search_container")});

這段代碼簡單的演示了在實例化的時候傳遞el屬性給View。下面咱們來看看模板的渲染。

var SearchView = Backbone.View.extend({    initialize: function(){
    },    render: function(context) {        //使用underscore這個庫,來編譯模板
        var template = _.template($("#search_template").html());        //加載模板到對應的el屬性中
        $(this.el).html(template(context));
    }
});var searchView = new SearchView({el: $("#search_container")});//這個reander的方法能夠放到view的構造函數中//這樣初始化時就會自動渲染searchView.render({search_label: "搜索渲染"});

運行頁面以後,會發現script模板中的html代碼已經添加到了咱們定義的div中。

這裏面須要注意的是在模板中定義的全部變量必須在render的時候傳遞參數過去,否則就會報錯。 關於el還有一個東西叫作$el,這個東西是對view中元素的緩存。

5.3 再來看view中event的使用

頁面上的操做除了能夠由以前的router來處理以外,在一個view中定義元素,還可使用event來進行事件綁定。這裏要注意的是在view中定義的dom元素是指你el標籤所定義的那一部分dom節點,event進行事件綁定時會在該節點範圍內查找。

來,繼續看代碼。

var SearchView = Backbone.View.extend({
    el: "#search_container",    initialize: function(){        this.render({search_label: "搜索按鈕"});
    },    render: function(context) {        //使用underscore這個庫,來編譯模板
        var template = _.template($("#search_template").html());        //加載模板到對應的el屬性中
        $(this.el).html(template(context));
    },

    events:{  //就是在這裏綁定的
        //定義類型爲button的input標籤的點擊事件,觸發函數doSearch
        'click input[type=button]' : 'doSearch'

    },    doSearch: function(event){        alert("search for " + $("#search_input").val());
    }

});var searchView = new SearchView();

本身運行下,是否是比寫$("input[type=button]").bind('click',function(){})好看多了。

5.4 View中的模板

上面已經簡單的演示了模板的用法,若是你用過django模板的話,你會發現模板差很少都是那麼回事。上面只是簡單的單個變量的渲染,那麼邏輯部分怎麼處理呢,下面來看下。

把最開始定義的模板中的內容換成下面這個。

<ul>
<% _.each(labels, function(name) { %>
    <% if(name != "label2") {%>
    <li><%= name %></li>
    <% } %>
<% }); %>
</ul>

下面是js代碼

var SearchView = Backbone.View.extend({
    el: "#search_container",    initialize: function(){        var labels = ['label1', 'label2', 'label3'];        this.render({labels: labels});
    },    render: function(context) {        //使用underscore這個庫,來編譯模板
        var template = _.template($("#search_template").html());        //加載模板到對應的el屬性中
        $(this.el).html(template(context));
    },

});var searchView = new SearchView();

再次運行,有木有以爲還不錯,模板中使用的就基本的js語法。

總結一下,關於view中的東西就介紹這麼多,文檔上還有幾個其餘的屬性,不過大致用法都一致。在之後的實踐中用到在介紹。

相關文章
相關標籤/搜索