BackBone及其實(shí)例探究_動力節(jié)點(diǎn)Java學(xué)院整理
MVC簡介
基本介紹
MVC即模型(Model),視圖(View)和控制(Controller),旨在實(shí)現(xiàn)Web系統(tǒng)的職能分工,具體來說就是使業(yè)務(wù)邏輯和數(shù)據(jù)顯示分離。
在MVC中,視圖(View)為用戶提供交互,模型(Model)負(fù)責(zé)處理數(shù)據(jù)和業(yè)務(wù)邏輯,控制器(Controller)則是View與Model之間溝通的橋梁。
MVC一個(gè)很重要的標(biāo)志就是,視圖(View)與模型(Model)沒有直接的交互,而是通過控制器(Controller)來溝通。具體地:用戶通過View進(jìn)行輸入,Controller負(fù)責(zé)把輸入傳遞給Model,Model處理,存取數(shù)據(jù),然后Controller將處理的結(jié)果返回View進(jìn)行展示。
優(yōu)缺點(diǎn)
MVC架構(gòu)的優(yōu)勢是顯著的,但也存在一些缺點(diǎn)。
一方面,MVC能極大地降低數(shù)據(jù)與視圖之間的耦合性,具有較高的可維護(hù)性和復(fù)用性,還能提高分工效率和降低生命周期的成本,從而有利于軟件工程化管理。
然而,MVC架構(gòu)卻不是那么容易理解,且會增加系統(tǒng)的復(fù)雜性,還會降低視圖層訪問數(shù)據(jù)層的效率,不適用于小型工程的開發(fā)。
Backbone
BackBone是一個(gè)重要的前端MVC框架,用于支持Javactript應(yīng)用的重量級開發(fā)。下面將對Backbone.Events(和控制器有著密切聯(lián)系)以及Backbone.Model(和模型有著密切聯(lián)系)的應(yīng)用進(jìn)行介紹,并結(jié)合實(shí)例分析Backbone框架是如何支持前端MVC的架構(gòu)的。所有的學(xué)習(xí)資料來自于BackBone官網(wǎng):http://backbonejs.org/
Backbone.Events
在Backbones中,事件可以作為一個(gè)任何一個(gè)對象的模型,對象能夠綁定和觸發(fā)一個(gè)事件被命名的事件。
對于一個(gè)被聲明了的對象object(下文的討論,所有的對象都以object為例),首先為object添加extend。
._extend(object,Backbone.Events);
然后為對象添加一個(gè)事件:格式為:
object.on(event,callback,[context]);
第一個(gè)參數(shù)為事件名,第二參數(shù)為事件調(diào)用時(shí)的回調(diào)函數(shù)。
以下面的事件為例:”alert”為事件名,function(msg)為回調(diào)函數(shù),msg為觸發(fā)事件時(shí)所傳入的參數(shù),與觸發(fā)器中的參數(shù)一致。
object.on(“alert”,function(msg){alert(msg);});
觸發(fā)object.on進(jìn)行回調(diào)的是object.trigger(“alert”, ”It's an event”)。
同object.on,object.trigger第一個(gè)參數(shù)為事件名,而第二個(gè)參數(shù)傳入的是object.on中回調(diào)函數(shù)所需要的參數(shù)。事件通過事件名被綁定在一個(gè)對象上??梢钥吹竭@個(gè)事件在綁定前是不需要聲明的,事件能夠被觸發(fā)的內(nèi)在聯(lián)系是共同的對象和事件名。特別地,如果事件名為”all”,那么調(diào)用任何object.trigger時(shí),都會觸發(fā)object.on中的回調(diào)函數(shù)。
與標(biāo)準(zhǔn)的事件綁定相對應(yīng)的,標(biāo)準(zhǔn)觸發(fā)的格式為:
object.trigger(event,[*arg]);
也可用js中類似屬性的定義來綁定一個(gè)對象的多個(gè)事件,如:
object.on{ “setup”:function_a(), “change”:function_b(), “destroy”:function_c() }
觸發(fā)相應(yīng)的”setup”,”change”,和”destroy”時(shí)可以分別調(diào)用相應(yīng)的function_a()等。
如果需要解除對象上一個(gè)事件的綁定,則使用object.off(event,callback,[context])函數(shù)。標(biāo)準(zhǔn)參數(shù)列表與相應(yīng)的object.on一致。
具體的,以上面的”setup”:function_a()為例:
//解綁定 object.off(“setup”,function_a); //移除所有的”setup”事件(可能綁定多個(gè)回調(diào)函數(shù)) object.off(“setop”); //移除所有的綁定function_a這個(gè)回調(diào)函數(shù)的事件 object.off(function_a); //移除所有的事件 object.off()。
如果希望事件被觸發(fā)一次就解綁定,則直接使用object.once(event,callback,[context])。
使用object.listenTo(other_object, event, callback),可監(jiān)聽其他對象的事件,事件被觸發(fā)時(shí)同樣調(diào)用callback的回調(diào)函數(shù)。類似的,可使用標(biāo)準(zhǔn)的stopListenTo([other_object], [event],[callback]),進(jìn)行解綁定。
ListenTo在MVC架構(gòu)中很有用,如使用視圖類的對象監(jiān)聽Model類的數(shù)據(jù)處理事件,并進(jìn)行回調(diào)(一般是對數(shù)據(jù)進(jìn)行展示)。
BackBone.Model
Models是一個(gè)Javascript應(yīng)用的核心。很多時(shí)候,models需要處理許多數(shù)據(jù),以及與這些數(shù)據(jù)相關(guān)的邏輯。然而,對于javascript來說,并沒有類似java那樣的類的結(jié)構(gòu)的存在。然而在實(shí)際應(yīng)用中,卻需要這樣的模型結(jié)構(gòu)。而BackBone.Model為js提供了很好的拓展,讓javascript也能實(shí)現(xiàn)類的結(jié)構(gòu)和功能,更準(zhǔn)確地說,實(shí)現(xiàn)類似C#中的屬性。下面給出官方介紹的一個(gè)簡化的實(shí)例(為了簡潔起見,之后所有介紹的模型都采用Model,而模型的對象都采用model):
//類似類的定義 var Model = BackBone.Model.extend({ myData:”year2013”, myFunction:function(){myData = “year2014”;} ); //類似類的實(shí)例化 var model = new Model; //類似對象調(diào)用成員方法 my_class.myFunction();
可以看到以上的代碼就實(shí)現(xiàn)了類似類的結(jié)構(gòu)。與傳統(tǒng)javascript對象的屬性區(qū)別在于,一個(gè)是具體的對象(只能使用一次),另一個(gè)是一個(gè)類的模型(可以被多次實(shí)例化)。
既然已經(jīng)有了類似類的實(shí)例化功能,那么自然,BackBone.Model也為我們提供了類似構(gòu)造函數(shù)的拓展。當(dāng)實(shí)例化一個(gè)對象時(shí),采用new Model([attributes], [options])的標(biāo)準(zhǔn)格式進(jìn)行實(shí)例化。例如:
new Model({ myData:”2013” });
此外,經(jīng)過拓展BackBone的js同C#一樣,還具有屬性的get和set函數(shù)。類似下面地進(jìn)行調(diào)用:
var date = model.get(myData); model.set(myData,”2014”);
此外,BackBone.Model還為js拓展了許多模型的默認(rèn)函數(shù),不一一介紹。需要使用的時(shí)候,建議在官網(wǎng)http://backbonejs.org/#Model-url的Model進(jìn)行查詢。
BackBone實(shí)例:Todo
下面結(jié)合官網(wǎng)中所給出的實(shí)例Todos來看一看BackBone在前端MVC的具體應(yīng)用。
這是一個(gè)純js實(shí)現(xiàn)的任務(wù)單application。
代碼中設(shè)計(jì)了四個(gè)“類”來實(shí)現(xiàn)任務(wù)單的功能:
//Model層面,實(shí)現(xiàn)一條任務(wù)的數(shù)據(jù)操作 var Todo = BackBone.Model.extend({}); //Model層面,實(shí)現(xiàn)整個(gè)任務(wù)欄的數(shù)據(jù)操作,Collection拓展了本地存儲功能 var TodoList = BackBone.Collection.extend({}); //BackBone.View.extend(),View和Controller層面 //負(fù)責(zé)接收用戶操作和修改Model的數(shù)據(jù),在render()函數(shù)中展示數(shù)據(jù) //與Todo的Dom元素相關(guān) var TodoView = BackBone.View.extend({}); //最頂層的UI以及控制器 var AppView = BackBone.View.extend({});
首先來分析實(shí)例中的Model,采用自下而上的分析方法:
Todo代表每一條Todo中的任務(wù),與之相關(guān)的邏輯是其是否已經(jīng)完成,需要指定其是否完成,需要初始屬性done:false,另外需要設(shè)置done的函數(shù),為此添加屬性:
toggle:function(){ this.save({done:!this.get(“done”);}); }
可以看到這個(gè)屬性在數(shù)據(jù)層從邏輯上實(shí)現(xiàn)了View層復(fù)選框的功能。
對于TodoList,使用Collection這一Model,為的是實(shí)現(xiàn)的數(shù)據(jù)本地存儲。
屬性含有model:Todo,即低層的,實(shí)現(xiàn)一個(gè)任務(wù)的實(shí)例。
此外,還需要localStorage : new BackBone.LocalStorage(“todos-backbone”)。用來進(jìn)行本地存儲。
在數(shù)據(jù)處理方面,需要對低層的done屬性進(jìn)行封裝,實(shí)現(xiàn)了done:function(),返回被改變的done的位置。
在View和Controller層面,自下而上地依次設(shè)計(jì)了下面兩個(gè)“類”。
var TodoView = BackBone.View.extend({}); var AppView = BackBone.View.extend({});
首先,對于TodoView,設(shè)置了一系列事件的響應(yīng),TodoView在Controller層面,對于View,接收這樣的事件監(jiān)聽:
events: { "click .toggle" : "toggleDone", "dblclick .view" : "edit", "click a.destroy" : "clear", "keypress .edit" : "updateOnEnter", "blur .edit" : "close" }
以clear()為例,clear中調(diào)用this.model.destroy()進(jìn)行數(shù)據(jù)層的處理,這就反饋到了數(shù)據(jù)層。
clear: function() { this.model.destroy(); }
另一方面,在初始化時(shí),指定了TodoView對數(shù)據(jù)層的this.model添加了監(jiān)聽,當(dāng)this.model的change事件發(fā)生,TodoView發(fā)生this.remove(render亦同),而這是表現(xiàn)層的內(nèi)容,這樣就反饋到了表現(xiàn)層。
initialize: function() { this.listenTo(this.model, 'change', this.render); this.listenTo(this.model, 'destroy', this.remove); }
這樣一來便完成了從View(輸入) -> Controller -> Model(處理) -> Contoller -> View(展示)的MVC架構(gòu)。從上面可以看到,從數(shù)據(jù)的接收,處理,返回,展示,所有過程都是自動的,且View和Model沒有任何的耦合。這是標(biāo)準(zhǔn)的MVC模式。
從TodoView向上則是總體的AppView。它的邏輯行為也是類似的,亦是在視圖層接收數(shù)據(jù),通過View類特有的結(jié)構(gòu)反饋到數(shù)據(jù)層,然后數(shù)據(jù)層又無耦合地將數(shù)據(jù)返回到視圖層進(jìn)行展示。但是作為最頂層的View和Controller,其在視圖層的render函數(shù)中實(shí)現(xiàn)的是總體的渲染,更底層的渲染則交給TodoView,在控制層的事件響應(yīng)和事件監(jiān)聽實(shí)現(xiàn)的則也是封裝度更高的處理。如添加一個(gè)todo,依次有如下的傳遞:
//View->Controller "keypress #new-todo": "createOnEnter" //Controller->Model createOnEnter: function(e) { if (e.keyCode != 13) return; if (!this.input.val()) return; Todos.create({title: this.input.val()}); this.input.val(''); } //Model -> Controller this.listenTo(Todos, 'add', this.addOne); //Controller -> View addOne: function(todo) { var view = new TodoView({model: todo}); this.$("#todo-list").append(view.render().el); }
在最后一個(gè)addOne函數(shù)中,則又包含了底層的MVC轉(zhuǎn)換流程,但是這顯然不是我們所關(guān)心的,它是由底層封裝好的,在Backbone的框架會自動地進(jìn)行MVC的邏輯傳遞。
Todo小結(jié)
這就是整個(gè)Todo Totuorial的結(jié)構(gòu)??偟恼f來,BackBone所為我們提供的這種特定的結(jié)構(gòu)很好地實(shí)現(xiàn)了MVC的架構(gòu),完成了View與Model的分離。而Controller則很好地充當(dāng)了轉(zhuǎn)換者的角色。
心得體會
由于之前沒有學(xué)習(xí)過前端MVC的知識,因此在探究Todo實(shí)例的時(shí)候遇到了很多困難。Todo實(shí)例與傳統(tǒng)的網(wǎng)頁應(yīng)用有很大的差異:
a) 無靜態(tài)html代碼,為純js實(shí)現(xiàn)
b) 數(shù)據(jù)與界面的交互原理十分難懂
c) View的構(gòu)建與數(shù)據(jù)的處理鴻溝太大。
d) 事件監(jiān)聽與事件綁定用途不同,響應(yīng)與回調(diào)流程容易混淆
一開始,真的很難理解Todo的結(jié)構(gòu),但是后來,反過來,從MVC的結(jié)構(gòu)來思考,從視圖開始分析,探究View->Controller->Model->Controller->View的線索。便得出了整體的結(jié)構(gòu)以及Controller的傳遞過程。可以說,理解Controller這個(gè)橋梁對于貫通整個(gè)MVC結(jié)構(gòu)有至關(guān)重要的作用。建議從View的輸入下手,對Controller進(jìn)行分析。
另一方面,可以適當(dāng)采取自上而下與自下而上的結(jié)構(gòu)進(jìn)行分析。如對View的分析,采用自上而下方法較為容易入手,而Models采用自下而上的方法能幫助我們更清晰地理解Models的結(jié)構(gòu)。
相關(guān)文章
實(shí)例講解JavaScript的Backbone.js框架中的View視圖
這篇文章主要介紹了實(shí)例講解JavaScript的Backbone.js框架中的View視圖,在瀏覽器端js框架backbone中我們用view來綁定和處理DOM事件,需要的朋友可以參考下2016-05-05全面解析JavaScript的Backbone.js框架中的Router路由
這篇文章主要介紹了Backbone.js框架中的Router路由功能,Router在Backbone中相當(dāng)于一個(gè)MVC框架中的Controller控制器功能,需要的朋友可以參考下2016-05-05require、backbone等重構(gòu)手機(jī)圖片查看器
這篇文章主要為大家詳細(xì)介紹了require、backbone等重構(gòu)手機(jī)圖片查看器的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Backbone中View之間傳值的學(xué)習(xí)心得
Backbone中的View就是用來展示由Model層傳出的數(shù)據(jù),或者在View里產(chǎn)生的一些數(shù)據(jù),本文給大家介紹Backbone中View之間傳值的解決方法,感興趣的朋友一起看下吧2016-08-08BackBone及其實(shí)例探究_動力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了BackBone及其實(shí)例探究,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07關(guān)于backbone url請求中參數(shù)帶有中文存入數(shù)據(jù)庫是亂碼的快速解決辦法
這篇文章主要介紹了關(guān)于backbone url請求中參數(shù)帶有中文存入數(shù)據(jù)庫是亂碼的快速解決辦法的相關(guān)資料,需要的朋友可以參考下2016-06-06JavaScript的Backbone.js框架的一些使用建議整理
這篇文章主要介紹了JavaScript的Backbone.js框架的一些使用建議整理,文中列的幾點(diǎn)主要還是針對DOM方面的操作,需要的朋友可以參考下2016-02-02深入解析JavaScript框架Backbone.js中的事件機(jī)制
這篇文章主要介紹了JavaScript框架Backbone.js中的事件機(jī)制,其中涉及到Backbone的MVC結(jié)構(gòu)及內(nèi)存使用方面的很多知識,需要的朋友可以參考下2016-02-02