三代目: M-V-C:(模型,視圖,控制器)
現(xiàn)在網(wǎng)上有很多關(guān)于mvc的介紹,讓人糾結(jié)的是他們各不相同,而且有的根本就說(shuō)的不對(duì), 對(duì)于框架模式這東西,沒(méi)有一個(gè)嚴(yán)格的規(guī)定說(shuō)這樣搞是 mvc 那樣就不是。 甚至連mvc本身也有很多變種,我們只要從根源上理解這個(gè)東西就行。
我就不扒祖墳了,咱們只需要知道它已經(jīng)存在了 30多年就行了。
我們思考一下 UI(圖形化用戶界面) 的本質(zhì):
為什么要有UI, 在計(jì)算機(jī)眼中 一切即數(shù)據(jù),其實(shí)要是深挖這個(gè)問(wèn)題,數(shù)據(jù)與操作其實(shí)都是 0 1 組成的機(jī)器碼,只不過(guò) CPU運(yùn)行的時(shí)候用指定寄存器的數(shù)據(jù)當(dāng)做指令罷了,也就是說(shuō)決定一個(gè)數(shù)據(jù)到底是數(shù)據(jù)還是指令 只取決于他所在的寄存器位置。(好了好了 扯遠(yuǎn)了,往回跑。。) 數(shù)據(jù)的操作是抽象的,是專業(yè)人士干的事情, 計(jì)算機(jī)為了走進(jìn)千家萬(wàn)戶, 必須提供一種傻瓜式的操作方式,于是UI誕生了。。。 用一句話解釋UI就是:
他是數(shù)據(jù)到圖像的一種映射程序;
剛才說(shuō)了它是一種映射程序,用戶通過(guò)操作圖像上的按鈕,來(lái)達(dá)到操作數(shù)據(jù)的目的,數(shù)據(jù)被用戶改變后,肯定需要從新生成映射。
請(qǐng)?jiān)试S我向上一張老掉牙的圖:
說(shuō)說(shuō)這里面 Modle View Controller 是干什么的:
1.
View: 放置視圖相關(guān)的代碼,原則上里面不應(yīng)該有任何業(yè)務(wù)邏輯。
2.
Controller: 放置視圖與模型之間的映射,原則上這里應(yīng)該很薄,他只放一些事件綁定相關(guān)的代碼(router),但并不實(shí)現(xiàn)真正的功能,他只是一個(gè)橋梁。
3.
Modle: 這里的modle不是說(shuō) 實(shí)體類, 他是主要實(shí)現(xiàn)邏輯的地方。
那還是上面 買(mǎi)水果的例子,那么在MVC下該如何設(shè)計(jì)呢:
概念 |
解釋 |
view層 |
放置界面代碼,以及一些刷新邏輯 如數(shù)據(jù)中的 0 1 轉(zhuǎn)成 男 女 |
controller層 |
放置一些綁定邏輯。完成router,不實(shí)現(xiàn)函數(shù)體。 |
model層 |
接收view的注冊(cè),當(dāng)自身數(shù)據(jù)變化時(shí),執(zhí)行view的刷新函數(shù)。 業(yè)務(wù)邏輯都在這里 |
他是這樣一個(gè)流程:
1.創(chuàng)建顯示蘋(píng)果數(shù)量的控件。
2.將上面控件注冊(cè)到model中。(設(shè)置關(guān)聯(lián)的數(shù)據(jù),–蘋(píng)果數(shù)變量)
3.修改model中 蘋(píng)果數(shù)變量 。
4.由于蘋(píng)果數(shù)變量被修改,觸發(fā)所有綁定在上面的控件(view)從新執(zhí)行刷新函數(shù)。
5.顯示蘋(píng)果數(shù)量的控件被更新。
這樣便解決了大部分界面與邏輯耦合的問(wèn)題,但是它并不完美:
View 和 Model 并不是完全脫離的,還是有一些邏輯耦合,因?yàn)樾枰鶕?jù)修改后的model從新刷新view。 難免view里面沾染一點(diǎn)model的結(jié)構(gòu)。
代碼量膨脹。
不方便進(jìn)行更精細(xì)的顆粒化控制。(因?yàn)関iew只知道 model被改了,但不知道誰(shuí)改的!)
- model在對(duì)應(yīng)多個(gè)view的時(shí)候,很難都伺候到位。
于是。。。
四代目: M-V-P:(模型,視圖,派發(fā)器)
請(qǐng)?jiān)试S我再上一張老圖:
針對(duì)mvc的一些問(wèn)題,在mvp模式下, 斬?cái)嗔?view 與 model的關(guān)系, 當(dāng)m 改變時(shí),m 通知 p 去改變v, 所以v變得更純潔(刷新邏輯被移動(dòng)到了p層), 為了保證m可以最大程度的復(fù)用 一部分業(yè)務(wù)邏輯也從 m 轉(zhuǎn)移到了p所以 mvp下 p 非常厚實(shí)。
mvp中最后改變v的是p那么在 v與p 之間會(huì)有一個(gè)接口,解決怎么轉(zhuǎn)換以及傳值的問(wèn)題。
五代目: M-V-VM:(模型,視圖,抽象視圖)
MVVM,最早來(lái)自于微軟社區(qū),用于WPF
Model-View-ViewModel的關(guān)系圖:
mvvm 與 mvp 的最大區(qū)別就是它使用
數(shù)據(jù)綁定(Data Binding)、依賴屬性(Dependency Property)、命令(Command)、路由事件(Routed Event) 來(lái)搞定與view層的交互, 但是這種綁定是與某種具體技術(shù)棧相關(guān)的, ViewModel從Model中抽象而來(lái),但更貼近于業(yè)務(wù)模型, 比如你Model中某字段是 true false, ViewModel中可能就是 “黑”,”白”等 這種更貼近業(yè)務(wù)場(chǎng)景的描述。 ViewModel中的屬性直接與某具體控件的屬性相綁定。 也就是說(shuō)當(dāng)某具體控件發(fā)生變化,ViewModel中的 某個(gè)字段就會(huì)跟著變化,然后Model中的字段也會(huì)進(jìn)一步變化。
以上述為例:
用戶使用UI修改了性別字段:
1.操作觸發(fā)綁定在UI上的事件(Data Binding 自動(dòng)完成)
2.事件進(jìn)入vm層,根據(jù)綁定規(guī)則,找出對(duì)應(yīng)的vm字段, (如表示性別的組件綁定的是vm中的sex字段)
3.vm上的sex被設(shè)置成true,(view層上值為”男” “女”,但是在抽象的vm層中我們用 bool 來(lái)表示這個(gè)字段)
4.同理尋找m層上的對(duì)應(yīng)字段,m上的sex被vm修改成1
5.m找到所有與sex字段有綁定關(guān)系的vm通知他們更新。
6.所有接到通知的vm更新sex字段。
7.vm尋找所有與sex字段有綁定關(guān)系的view層控件,通知他們更新(Data Binding 自動(dòng)完成)。
8.view被更新。所有涉及到sex字段的組件都被刷新。
有時(shí)候這個(gè)流程未必是從 1 步開(kāi)始,如果直接對(duì) m 進(jìn)行修改,則就是從第 4 步開(kāi)始的。
同理如果沒(méi)有view層,則沒(méi)有必要進(jìn)行 7 , 8步驟。
這就是說(shuō) mvvm 下可以完全干掉 view 層, 方便的進(jìn)行自動(dòng)化測(cè)試。
小結(jié) (推送/訂閱 這個(gè)是數(shù)據(jù)驅(qū)動(dòng)的核心)
不管是 mvc 還是 mvp 或 mvvm ,他們都是
數(shù)據(jù)驅(qū)動(dòng) 的。核心上基于
m 推送消息,v或p來(lái)訂閱 這個(gè)模型。使用者需要維護(hù)的不再是 UI 樹(shù),而是抽象的數(shù)據(jù)。(通過(guò)數(shù)據(jù),可以隨時(shí)構(gòu)建出新的 UI 樹(shù)), 當(dāng) UI 的狀態(tài)一旦多起來(lái),這種框架模式的優(yōu)勢(shì)便體現(xiàn)出來(lái)了。 因?yàn)榫S護(hù)數(shù)據(jù)可比維護(hù) UI 狀態(tài)爽多了。
前端中的mvc:
并不是說(shuō) m v c 三者一定要獨(dú)立出現(xiàn)才行,比如 Backbone。js 它的 controller 層只是一個(gè) router。 其實(shí)在傳統(tǒng) mvc 中 controller 里本來(lái)就沒(méi)有太多的邏輯,他只是一個(gè)事件的”傳遞者”, 加之 javascript 中人們習(xí)慣使用匿名函數(shù)當(dāng)事件回調(diào),這樣就等于直接在 view 層中把功能函數(shù)實(shí)現(xiàn)了。 所以 view 與 controller 合并 或者 controller 與model 合并都有可能。
JavaScript
1
2
3 |
$(xxx).click(function(e){
console.log(e);
}) |
本文版權(quán)歸傳智播客web前端開(kāi)發(fā)學(xué)院所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明作者出處,謝謝!
作者:傳智播客web前端培訓(xùn)學(xué)院;
首發(fā):http://metathetuscanyresort.com/web/