當(dāng)下前端開發(fā)框架設(shè)計(jì)顯然已經(jīng)在mvvm方式上又發(fā)展了一步,virtual dom提出不久,使用前端代碼來(lái)調(diào)用native的思路就開始被實(shí)踐。相信大家也知道是什么東西。到了今天,我們不得不承認(rèn),mnv* 框架開發(fā)時(shí)代已經(jīng)到來(lái)。

mnv是什么,具體可以這么理解,model-Native-View-*,而后面的則可以認(rèn)為是 virtual dom 或mvvm 中的 ViewModel,或者我們也可以自己使用controller來(lái)實(shí)現(xiàn)的調(diào)用方式。想想這樣定義是非常合適的。相比之前的不同,就是用nativeView 代替了 htmlView。那么我們?cè)倏聪聫膁om api 到mnv*,我們?yōu)槭裁磿?huì)看到這樣的變化。

1.dom交互

在此之前不得不提下之前的dom交互框架,就是直接選擇找到特定的dom進(jìn)行操作,思路十分直接也很實(shí)用,通過(guò)dom交互框架,相比Java原生API,我們可以比較高效地處理dom的改變和事件綁定了,這種高效的方式給我們帶來(lái)了效率上的提高,但是頁(yè)面復(fù)雜了就不好處理了。

隨著ajax技術(shù)的盛行,SPA應(yīng)用開始被廣泛運(yùn)用。SPA的引入將整個(gè)應(yīng)用的內(nèi)容都在一個(gè)頁(yè)面中進(jìn)行異步交互。這樣,原有的dom交互方式開發(fā)就顯得不好管理,例如某SPA頁(yè)面上交互和異步加載的內(nèi)容很多,我們的做法是每一次請(qǐng)求渲染后做事件綁定,異步請(qǐng)求后再做另一部分事件綁定,后面以此類推。當(dāng)所有異步頁(yè)面全部調(diào)用完成,頁(yè)面上的綁定將變得十分混亂,各種元素綁定,渲染后的視圖內(nèi)容邏輯不清,又不得不聲明各種變量保存每次異步加載時(shí)返回的數(shù)據(jù),因?yàn)轫?yè)面交互需要對(duì)這些數(shù)據(jù)做操作,最后寫完,項(xiàng)目代碼就成了一鍋粥。

2.前端mvc

為了更方便地統(tǒng)一管理頁(yè)面上的事件、數(shù)據(jù)和視圖內(nèi)容,就有了早期mvc的框架設(shè)計(jì)。mvc可以認(rèn)為是一種設(shè)計(jì)模式,其基本思路是將dom交互的過(guò)程分為調(diào)用事件、獲取數(shù)據(jù)、管理視圖。即將之前所有的事件、數(shù)據(jù)、視圖分別統(tǒng)一管理。用model來(lái)存放數(shù)據(jù)請(qǐng)求和數(shù)據(jù)操作,視圖來(lái)存放對(duì)視圖的操作和改變,controller用來(lái)管理各種事件綁定。

例如,SPA中的每個(gè)異步頁(yè)面可以看成是一個(gè)組件,之前的做法是每個(gè)組件獨(dú)立完成自己的數(shù)據(jù)請(qǐng)求操作、渲染和數(shù)據(jù)綁定,但是組件多了,每個(gè)組件自己去做就比較混亂,邏輯比較混亂。到了mvc里面,所有的組件數(shù)據(jù)請(qǐng)求、渲染、數(shù)據(jù)綁定都到一個(gè)統(tǒng)一的model、view、controller注冊(cè)管理。后面的操作我們就不再管你有多少個(gè)組件了,你要調(diào)用必須要通過(guò)統(tǒng)一的model、view、controller來(lái)調(diào)。通俗來(lái)說(shuō)就像是組件交出了自己控制權(quán)到一個(gè)統(tǒng)一的地方注冊(cè)調(diào)用,這樣就方便了很多,相信大家都已經(jīng)了解過(guò),這里就省篇幅不舉例了。

3.前端mvp

mvp可以跟mvc對(duì)照起來(lái)看,而且我們也很少專門去關(guān)注它。和mvc一樣,mvc的M就是Model, V就是View,而P,則代表Presenter,它與Controller有點(diǎn)相似。不同的是,在mvc中V會(huì)直接展現(xiàn)M,而在mvp中V會(huì)把所有的任務(wù)都委托給P。V和P會(huì)互相持有reference,因此可以互相調(diào)用。

例如我們可以在mvc代碼上做一點(diǎn)改變,寫成這樣:

幾個(gè)好處,這樣將view和Controller的引用關(guān)聯(lián)了起來(lái),而mvc一般是通過(guò)事件監(jiān)聽或觀察者的異步方式來(lái)實(shí)現(xiàn)的,我們可以在任意地方定義注冊(cè)監(jiān)聽事件都不會(huì)有問(wèn)題,這樣監(jiān)聽的事件和觸發(fā)這個(gè)事件的html元素脫離了引用,當(dāng)應(yīng)用復(fù)雜起來(lái)后要維護(hù)dom的交互邏輯就比較麻煩了。而mvp提供了一個(gè)簡(jiǎn)單的引用,將元素對(duì)應(yīng)的操作與對(duì)應(yīng)的presenter關(guān)聯(lián)起來(lái)。我們要查詢?cè)貙?duì)應(yīng)的controller時(shí)只要通過(guò)Controller.vp就可以直接調(diào)用了,其實(shí)這個(gè)時(shí)候就和mvvm的定義方式有點(diǎn)類似了,不是嗎?

4.前端mvvm

mvvm概念可以認(rèn)為是一個(gè)自動(dòng)化的presenter,也在這個(gè)時(shí)候進(jìn)一步弱化了C層,任何操作都通過(guò)viewModel來(lái)驅(qū)動(dòng)。Controller最終在頁(yè)面上的行為通過(guò)directives的形式體現(xiàn),通過(guò)對(duì)directives的識(shí)別來(lái)注冊(cè)事件,這樣管理起來(lái)就更清晰了。

看一個(gè)mvvm框架定義的例子:

和mvp的定義比較,有點(diǎn)類似,mvvm設(shè)計(jì)一個(gè)很大的好處是將mvc中controller中的controller注冊(cè)到相對(duì)應(yīng)的元素中,讓我們后期維護(hù)時(shí)很快定位,免去了查看controller中event列表的工作,而且初始化后自動(dòng)做數(shù)據(jù)綁定,能將頁(yè)面中所有同類操作復(fù)用,大大節(jié)省了我們自己寫代碼做綁定的時(shí)間。這段代碼中初始化時(shí)自動(dòng)幫我們就做了數(shù)值填充、數(shù)據(jù)雙向綁定、事件綁定的事情。

那么框架怎樣幫我做的呢。我們來(lái)看下newVM做了哪些事情:這里傳入了元素、數(shù)據(jù)、方法列表、自定義directive列表,首先程序找到這個(gè)元素,開始對(duì)這個(gè)元素的屬性節(jié)點(diǎn)進(jìn)行遍歷,一旦遍歷到屬性名稱含有q-開頭的屬性是,認(rèn)為是mvvm框架自定義的屬性,然后會(huì)對(duì)屬性的指進(jìn)行特殊處理;例如遍歷到q-html="label"時(shí),將data中的label值賦給這個(gè)元素的innerHTML;如果遍歷到q-on="click: submit"時(shí),將這這個(gè)元素上綁定click事件,事件回調(diào)函數(shù)為submit;也可以自定義q-mydo的指令,遍歷到該節(jié)點(diǎn)屬性是,調(diào)用directive中的mydo方法,輸入?yún)?shù)為data中的getValue方法返回的值,getValue輸入?yún)?shù)為number值,這里的getValue被稱為過(guò)濾器。

這里要知道的是q-開頭的屬性指令是框架約定的,不同的框架約定的不一樣,例如ng-、v-、ms-,這些大家也都見過(guò)或用過(guò)。這里viewModel創(chuàng)建進(jìn)行綁定的原理就這么簡(jiǎn)單,按照這個(gè)思路去擴(kuò)充,就可以自己寫一個(gè)mvvm框架。當(dāng)然完整的框架涉及東西多的多,含有豐富的directive、filter、表達(dá)式、vm完善的api和甚至一些兼容性處理等。

總結(jié)來(lái)說(shuō)從mvc到mvp,然后到mvvm,前端設(shè)計(jì)模式仍然是向著易實(shí)現(xiàn)、易維護(hù)、易擴(kuò)展的基本方向發(fā)展的。但目前前端各類框架也已經(jīng)成熟并開始版本迭代。但是,這還沒有結(jié)束,我們依然沒有脫離dom編程的基本套路,一次次框架的改進(jìn)只是提高了我們的開發(fā)效率,但是dom元素的效率仍沒有得到本質(zhì)的提升。

5.前端virtual dom

為了改進(jìn)dom交互的效率,或者說(shuō)是盡量減少dom交互的次數(shù),virtual dom的概念當(dāng)下十分盛行,目前圈內(nèi)各種大小團(tuán)隊(duì)紛紛投入項(xiàng)目使用。因?yàn)関iewModel的改變最終還是要實(shí)時(shí)操作dom來(lái)刷新view層,而dom對(duì)象的操作相對(duì)于Java對(duì)象的操作仍然是要慢些。原因很簡(jiǎn)單,dom節(jié)點(diǎn)對(duì)象的內(nèi)置屬性很多,就創(chuàng)建一個(gè)dom對(duì)象而言,dom的創(chuàng)建需要處理各種內(nèi)置屬性的初始化,而如果使用Java對(duì)象來(lái)描述就簡(jiǎn)單了。

使用virtual dom,頁(yè)面的渲染過(guò)程不再是數(shù)據(jù)直接通過(guò)前端模板渲染到頁(yè)面,也不是初始化viewModel進(jìn)行頁(yè)面模板填充和事件綁定,而是通過(guò)dom衍生描述語(yǔ)法(這為什么稱為DOM衍生描述語(yǔ)法,通常我們通過(guò)html來(lái)描述,但是目前一些框架是通過(guò)非標(biāo)準(zhǔn)的html的方式描述的,定義的一套迎合自己框架的方式,其實(shí)使用html也是可以的)解析生成virtual dom,頁(yè)面交互變成了是修改virtual dom,然后將virtual dom的改變反映到htmlView層上。

可以使用如下java來(lái)表示:

如果java對(duì)象children屬性第三個(gè)元素要被移除,同時(shí),添加一個(gè)class為ui-list-item2的li節(jié)點(diǎn),則首先需要對(duì)java對(duì)象進(jìn)行修改記錄所有的操作,最后將修改的vitual dom變化反映到頁(yè)面上:

這里的java對(duì)象就相當(dāng)于virtual dom,用戶的某個(gè)交互操作可能導(dǎo)致dom的多個(gè)地方,如果沒有vitual dom,那可能就要進(jìn)行多次dom操作,virtual dom則可以將多個(gè)用戶交互操作反映在virtual dom上,最后做的virtual dom DIFF算法然后再dispatch到頁(yè)面view層上。相對(duì)于mvvm,在頁(yè)面初始化渲染階段,也避免了掃面節(jié)點(diǎn),解析directives,要知道這些操作都是dom操作,使用virtual dom顯然能將頁(yè)面渲染速度提高不少。

6.前端mnv*

如果說(shuō)vitual dom減少了dom的交互次數(shù),那么mnv*想要做的一件事情就是完全拋棄使用dom,那樣就只能在view層做改進(jìn)了,使用nativeView來(lái)代替目前html的view,而交互邏輯依然可以使用viewModel、virtual Dom或者controller來(lái)實(shí)現(xiàn),具體就看實(shí)現(xiàn)的方式了。

要做到NativeView的操作,這里與之前不同之處就是調(diào)用時(shí)通過(guò)衍生HTML語(yǔ)法通過(guò)解釋器執(zhí)行nativeView的渲染,這時(shí)就需要在native和衍生HTML語(yǔ)法之間添加一層解釋器來(lái)解析現(xiàn)有的view描述語(yǔ)法了。比如我們看一個(gè)渲染Native的例子:

這里和vitual dom框架類似的地方都是都使用衍生的html描述語(yǔ)法來(lái)表示view層,而不同的是mnv模式是調(diào)用的nativeView來(lái)實(shí)現(xiàn)的衍生html的view展示。其實(shí)這里和上節(jié)中的實(shí)現(xiàn)唯一不同的地方是這里的view是native view。當(dāng)然這只是一種實(shí)現(xiàn),目前mnv的實(shí)現(xiàn)方案已經(jīng)不止一種了,有人已經(jīng)實(shí)踐了通過(guò)mvvm的編程方式來(lái)將viewModel渲染轉(zhuǎn)化為native view的方案。

7.總結(jié)

總結(jié)下來(lái),前端框架一次次進(jìn)化,先從效率的方向上提升,然后在性能上完善,這里只是想提出mnv*的一個(gè)概念來(lái)描述前端native開發(fā)的這個(gè)階段。目前mnv的開發(fā)模式開始進(jìn)入視線,也在快速地形成和建立生態(tài)。但盡管如此,我們?nèi)绻枰x擇技術(shù)棧方案,當(dāng)然還是以最適合我們的作為最高原則。切忌過(guò)度設(shè)計(jì)。

作者簡(jiǎn)介:張成文,英文名Ouven,校導(dǎo)web前端開發(fā)工程師,前騰訊web前端工程師,對(duì)前端領(lǐng)域的技術(shù)知識(shí)具有較高的職業(yè)能力和探究精神。對(duì)前端響應(yīng)式頁(yè)面設(shè)計(jì)、工程構(gòu)建組件化、mv*設(shè)計(jì)實(shí)現(xiàn)、前端優(yōu)化、ES6開發(fā)體系、前端開發(fā)知識(shí)體系等有深入的研究和項(xiàng)目實(shí)踐。

1.《校導(dǎo)張成文 | mnv*框架開發(fā)時(shí)代》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無(wú)關(guān),侵刪請(qǐng)聯(lián)系頁(yè)腳下方聯(lián)系方式。

2.《校導(dǎo)張成文 | mnv*框架開發(fā)時(shí)代》僅供讀者參考,本網(wǎng)站未對(duì)該內(nèi)容進(jìn)行證實(shí),對(duì)其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。

3.文章轉(zhuǎn)載時(shí)請(qǐng)保留本站內(nèi)容來(lái)源地址,http://f99ss.com/guonei/367.html