前言
了解前端的演化之路需要知道的兩件事
- 架構(gòu)不是一天實(shí)現(xiàn)而是演化出來(lái)的 </br>
- 架構(gòu)的出現(xiàn)是為了解決一個(gè)或者一類(lèi)問(wèn)題的
</br>
UI包含什么通今?
在討論UI框架之前垒棋,我們先來(lái)了解一個(gè)頁(yè)面可能有的內(nèi)容眶蕉,一個(gè)UI頁(yè)面正常包含的內(nèi)容有
- 綁定事件遂蛀,即響應(yīng)用戶(hù)的操作,常見(jiàn)的事件有點(diǎn)擊窜醉,長(zhǎng)按埋同,滾動(dòng)
- 向業(yè)務(wù)獲得業(yè)務(wù)模型
- 展現(xiàn)模型蚯根,包括設(shè)置呈現(xiàn)內(nèi)容琼锋,調(diào)整顯示圖層等
- 動(dòng)畫(huà)
- 顯示
正常他們的流程關(guān)系?如下圖:
正常來(lái)說(shuō)放闺,一個(gè)頁(yè)面的大部分內(nèi)容都應(yīng)該是源自業(yè)務(wù)的,只有少數(shù)部分是用戶(hù)操作引起的頁(yè)面內(nèi)容改動(dòng)與業(yè)務(wù)無(wú)關(guān)(如滾動(dòng))
</br>
蠻荒時(shí)代
在互聯(lián)網(wǎng)剛出現(xiàn)的時(shí)代缕坎,web端的html怖侦,js是全部寫(xiě)在一起的,同一個(gè)html既處理UI又處理業(yè)務(wù)谜叹,這種做法在那個(gè)剛起步的時(shí)代并沒(méi)有什么問(wèn)題匾寝,但隨著業(yè)務(wù)的發(fā)展,邏輯日趨復(fù)雜荷腊,這種做法的弊端開(kāi)始出現(xiàn)艳悔,整個(gè)業(yè)務(wù)邏輯變得復(fù)雜而難以維護(hù)
</br>
MVC時(shí)代 (web端主流框架,大部分移動(dòng)端系統(tǒng)的默認(rèn)架構(gòu))
MVC的到來(lái)女仰,就是為了解決邏輯混雜的問(wèn)題猜年,從而將頁(yè)面簡(jiǎn)單的進(jìn)行功能劃分,M負(fù)責(zé)處理業(yè)務(wù)疾忍,V負(fù)責(zé)顯示乔外,C負(fù)責(zé)設(shè)置V顯示內(nèi)容,響應(yīng)V事件并調(diào)用M處理一罩,MVC最明顯的優(yōu)點(diǎn)是杨幼,M的開(kāi)發(fā)完全獨(dú)立,不再需要考慮頁(yè)面如何顯示聂渊,而是直接的面相業(yè)務(wù)邏輯差购,V的開(kāi)發(fā)也不需要考慮業(yè)務(wù)需要顯示什么模型,而是直接面對(duì)顯示結(jié)果 </br>
這是一個(gè)基礎(chǔ)的MVC結(jié)構(gòu)顯示
MVC只是對(duì)原有頁(yè)面的簡(jiǎn)單拆分,所以汉嗽,還是存在部分問(wèn)題的
在這個(gè)簡(jiǎn)單的MVC例子歹撒,短短的40多行代碼中,混合了事件綁定诊胞,業(yè)務(wù),UI顯示操作锹杈,動(dòng)畫(huà)撵孤,一旦頁(yè)面邏輯稍微復(fù)雜,C就會(huì)嚴(yán)重膨脹竭望,影響編寫(xiě)與閱讀
</br>
MVP時(shí)代
為了解決MVC遇到的問(wèn)題邪码,MVP(Model - View - Presenter)隨之出現(xiàn),MVP中的V是大V咬清,順序不是MVP闭专,嚴(yán)格來(lái)說(shuō)奴潘,MVP應(yīng)該叫(Model - Presenter - Controller - View),他將頁(yè)面的業(yè)務(wù)邏輯從C中拆分出來(lái)影钉,放入P中画髓,從而達(dá)到獨(dú)立頁(yè)面邏輯,最終達(dá)到頁(yè)面顯示/頁(yè)面邏輯都可以單獨(dú)測(cè)試的效果
經(jīng)過(guò)拆分后平委,P在編寫(xiě)的時(shí)候已不需要考慮V具體怎么實(shí)現(xiàn)奈虾,只需要關(guān)心響應(yīng)什么事件,向V提供什么模型
而VC也只需要關(guān)心模型怎么展現(xiàn)廉赔,在什么位置響應(yīng)用戶(hù)的操作
還是同樣的例子肉微,但是把業(yè)務(wù)拆分到Presenter
但MVP也不是沒(méi)有缺點(diǎn)的,試想一下這種情況,我們現(xiàn)在需要顯示一個(gè)列表,我們使用一個(gè)為Activity增加了一個(gè)Adapter顯示這個(gè)列表
這時(shí)候蜡塌,產(chǎn)品說(shuō)我們需要增加一個(gè)昵稱(chēng)碉纳,這個(gè)昵稱(chēng)從另一個(gè)服務(wù)獲得,我們來(lái)看看這時(shí)候我們需要改動(dòng)什么馏艾,我們需要在頂層View(也就是Activity)上增加一個(gè)回調(diào)劳曹,
接著,我們需要在Adapter上增加一個(gè)方法攒至,刷新全部
這時(shí)候我們思考下厚者,
- 我們只是要在列表的單項(xiàng)里面增加一個(gè)顯示內(nèi)容,但我們卻需要在他的父層級(jí)改動(dòng)
2.我們改動(dòng)的是item迫吐,卻不得不刷新整個(gè)列表
對(duì)MVP的Presenter來(lái)說(shuō)库菲,View是單一的,意味著模型只能夠傳遞到最頂層的View志膀,再由頂層View逐級(jí)下發(fā)熙宇,一旦傳遞的模型增加,傳遞的層級(jí)加深溉浙,這部分就內(nèi)容就非常容易膨脹烫止,那如果底層的View能直接從P那邊得到數(shù)據(jù)呢?MVVM的出現(xiàn)就是為了解決這么一個(gè)問(wèn)題
</br>
MVVM時(shí)代
MVVM是一個(gè)基于模型綁定的框架戳稽。通過(guò)在V上增加對(duì)VM的監(jiān)聽(tīng)馆蠕,使P對(duì)VM的修改直接反應(yīng)到V上,從而避免P的每一次修改都需要從主View逐級(jí)傳遞到子View上惊奇。
MVVM的V跟MVP一樣也是大V互躬,包含Controller和View,網(wǎng)上有些Demo把業(yè)務(wù)也集合進(jìn)VM颂郎,但這里為了邏輯清晰吼渡,并且方便測(cè)試,我們將VM也業(yè)務(wù)獨(dú)立出來(lái)乓序,也就是把P獨(dú)立出來(lái)寺酪,所以坎背,整個(gè)框架應(yīng)該是 M(P)VM(C)V
我們?cè)贏ctivity初始化的時(shí)候構(gòu)造一個(gè)ViewModel,Present則由ViewModel來(lái)構(gòu)造(為了使View對(duì)業(yè)務(wù)透明)寄雀,ViewModel向View提供顯示需要的業(yè)務(wù)模型得滤。而對(duì)于底層的View來(lái)說(shuō),只需要傳入一個(gè)ViewModel咙俩,接下來(lái)他的所有顯示就與上層View無(wú)關(guān)了耿戚。ViewModel的任何改動(dòng),不再需要頂層View介入阿趁,就能傳遞到底層了
經(jīng)過(guò)MVVM改造后膜蛔,頂層View只有在構(gòu)造的時(shí)候需要傳入ViewModel,其他任何時(shí)候脖阵,底層View都能直接通過(guò)ViewModel獲得自己要顯示的內(nèi)容皂股,每一個(gè)底層View都是最小單元的MVC,具體底層View怎么顯示已經(jīng)與他的上層沒(méi)有任何關(guān)系命黔,ViewModel增加Field也不再需要通過(guò)頂層View傳遞進(jìn)來(lái)呜呐,下層View能直接通過(guò)ViewModel獲得