后MVC時代的前端架構

TabathaMatt 7年前發布 | 11K 次閱讀 MVC模式 MVVM模式 前端技術

很多人覺得,前后端的差異主要是分別承載了數據和樣式,功能和皮膚。前端就是視覺方面的,后端是實質性的。追溯到很多年前,確實是這樣的,所謂的前端只是由于后端MVC中的View過于復雜,為了提升用戶體驗,提高加載速度,以及降低服務器壓力,所衍生出的一些優化技術。

前端框架演進

最初前端沒有架構,也不需要。但隨著UI交互的復雜度激增,我們發現API提供的數據仍然需要進行處理,再進行渲染,而分離這些需要處理的數據和視覺渲染部分后又需要一層進行控制,自然而然,將后端的MVC照搬了過來。但其實人們并沒有發現,并不是我們把MVC搬到了前端,而是把后端的V搬到前端之后又分成了MVC,這個問題暫且擱下,后面會解釋。

接著前端又再一次的變得復雜,尤其是不同交互對于同一資源的操作,導致過程化的控制器過于臃腫,而不堪重負,MVVM應運而生。人們都以為,MVVM就是把C變成了ViewModel,但是ViewModel是一個實體,如何控制呢?真正用會MVVM的開發者都會發現,MVVM提倡的是定義而不是控制,定義M和V的關系,什么樣的Model應該呈現什么樣的View,然后一切自然而然的隨著用戶的行為去改變。

其實原先的C被更高度的抽象了,變成了框架的一部分,讀取M和V的關系,并監聽他們,在一方改變的時候根據關系修改另一方,達到雙向綁定。而ViewModel其實是為了描述這一關系而抽象出來的Model,因為它是相對于Model更偏向View的,所以叫ViewModel。接著出現的一系列MVWhatever很好的說明了ViewModel并不是C變的,人們以為既然C可以變成VM,那也可以變成別的。殊不知,ViewModel也是一種Model,它是由View分裂出來的,而View只能分裂出Model和View,不會出現別的。

樣式和數據的區別

React橫空出世,卻沒有人能說清楚它到底是MV什么,甚至許多人搞不清M在哪,最后干脆說React就是個View。那么React到底是什么架構呢?先別急,我想先講一個故事:

有一個語言學者提出一個觀點 - 法國人的數學很爛,為什么呢?因為法語中的quatre-vingt(80)的意思是 4個20,居然都不會把4乘以20計算出來,是不是數學很差?

第一次聽到這個故事,我感到很好笑,難道漢語就不是這樣了嗎?我們叫做“八十”,其實還是8個10,和4個20有什么區別,還不是都沒有計算。后來再一想,不僅不是,而且法國人數學應該很好,因為漢語遵循了現代通用的10進制,而法語是20進制和10進制混合的,所以他們大腦可以自然的映射10進制和20進制,就好比是左撇子為了迎合右撇子的世界而變得思維敏捷一樣的道理。

講到這里,可能你會覺得莫名其妙,這跟前端有什么關系。其實我只是想說明一個道理,我們經常會被一瞬間的思考誤導,比如這個故事中,人們會把習慣的“八十”看做是一個獨立的東西,而嘲笑法國人他們的“quatre-vingt”,其實我們只是習慣了這種計算,或者說在大腦中建立了映射,就忽略了計算,而將其看做一個整體。由此說明,我們在看到一個信息的時候是會進行無意識計算的,從而你會認為你看到的就是那個東西本身,并不需要計算。我們認為‘八十’是一個對象,而不是表達式,但事實是沒有符號可以表達80這個數,所以用‘八個十’的表達式來表示,只不過我們太熟練所以自動計算了。

拋棄固有思維,現在假設@為81進制數的最大數,既80,再假設有一種操作符可以把十進制變成81進制數,這一過程是不是數據的計算?但如果有一種字體格式可以把連在一起的8和0兩個數字變成@的樣子,這算不算樣式的改變?也許你會覺得通過操作符是在計算機中當做了@,而字體只是長得像,但計算機真正認識的只有可能是二進制binary,所以整個過程是不是也可以看做都是樣式?還有人會說,數據無論變成什么樣式它本身都不會變,而樣式會變。但如果顯示器有色差呢,你看到的藍色就真的是藍色嗎?樣式沒變,你看到的仍然會變。

其實數據和樣式本質沒有區別,區別只在于程度,從計算機到人類的理解程度。差異來自于我們自己,我們把難以理解的叫數據,容易理解的叫樣式,計算時間長的叫數據,計算時間短的叫樣式。一個矩形你知道是樣式,一個長xx,寬xx,邊框為xx的東西你會以為是數據,但對于程序來說其實是一樣的。處理一下,得到另一種形式的等同的東西,這就是一個不斷翻譯的過程,從二進制翻譯到人類語言,甚至到非語言的一種印象,比如視覺,語音,甚至意識。無論是什么,都是讓人類更容易理解。

Component架構

耗費了這么大的篇幅說明樣式和數據沒有區別的目的其實是為了解釋React的架構。前面說到的MVC和MVVM其實都是對于View的一種演進,因為所謂View才是最復雜的,為什么說所謂呢,基于前面的結論,View就是Model,但它是人們難以理解的部分,所以沒有被抽象為Model,而是直接顯示出來讓用戶自己去讀。為了便于理解,想象一種極端的情況,Model只有二進制形式,直接顯示給了用戶,理論上來說,用戶是可以看懂的,只是難度高了一點點。而從View抽象成Model的過程,其實就是程序將二進制翻譯出來的過程。而框架的所做的改進就是翻譯程度的提升,讓用戶更容易的讀取。

回到React身上,它的架構就十分清晰了,前面的MVC是把后端的View分離出了一部分Model,而MVVM,是把MVC的V又分離了一部分Model出來。React所做的猶如它的版本號一般,直接起飛,每個Component其實都是View分離出來的Model,理論上來說,你能抽象出無限層Component,這個極限上,View已經簡單的沒有意義了。而實際來說,你可以視項目情況而定,把View抽象到某個程度后扔給用戶自己閱讀。而由于分成無數層,M到V的過程也變得簡單,不再需要控制,因為復雜的計算已經被分解成了極簡單的計算分散到每一層中了,甚至有時候僅僅是Component為傳入的props加上一些字面量,然后傳入另一個Component,或者是分解或組合成Object再向下傳遞。一旦真的理解了View即是Model的思想,你就會發現,React似乎什么也沒做,其實卻把什么都做了,而且非常簡單。

但Component這種架構也有其問題所在,那就是太過于松散,對架構設計的要求比較高。一旦你并非基于由機器到人類的理解程度來抽象分層你的Component,其復用性和擴展性就會大大降低。

前端面向對象

前面說到了View和Model沒有本質上的區別,那么前端架構和后端架構為什么會有區別呢?原因很簡單,后端可以把未翻譯完的數據丟給前端,但前端不能隨隨便便丟給用戶,所以前端變成了多層MV,而不是后端簡單的分為了一層MV。前端面向對象的設計也更加的困難,尤其是擁有多年后端開發經驗的開發人員,更容易誤導自己,因為在后端翻譯完成的東西,在前端就變成了最原始的東西。

舉個例子,就拿最常見的電商說事吧,設計一個商品頁面的Component架構。在擁有所謂數據的時候,它是某一個商品的頁面,比如一件印著國旗的T恤。但顯然我們的代碼庫在運行之前是沒有這個從數據庫傳過來的數據的,所以我們沒法把它抽象成一個叫做NationalFlagTShirtPage的Component的。退而求其次,在失去后端數據之后,它應該是一個衣服類的商品頁面,比如有一些尺碼對照和試衣功能,所以可以有一個叫做ClothesShowcase的Component。說到后端數據的這一層,并不是為了搞笑,它反映出了一個問題。其實后端對于前端,就是上一層的Component。同理,在下一層的Component中,我們也應該忽視這一層傳入到下一層的數據,因為它不應該有這個數據。

比如ClothesPage還應該包含一個顯示圖片的區域,和一個顯示尺碼信息的區域。這時,很多人會在ClothesShowcase的里面再放一個ClothesImage和ClothesInformation,但是在上一層作為代碼一部分的’Clothes’,在這一層應該已經被忽略,我們應該放入ProductImage和SizeInformation。只有當ClothesPage調用SizeInformation并傳入’S’,’M’,’L’之類衣服尺碼作為參數的時候,它才是衣服尺寸,而它自身應該僅僅是尺寸信息的Component。我們會發現,上一層的代碼(字面量’L’等),變成了下一層的數據,如此一直下去,所有的特性都會變成數據,而代碼,可能僅僅是一些最基礎的元素,比如按鈕,方框之類的,甚至是HTML本身。

如果一直使用對于后端來說的數據層面的’clothes’的話,就只能一次把ClothesPage這個Component寫好,而沒法繼續抽象了。而其子Component可能僅僅是由于過于臃腫而強行分割的patial了。這樣做除了代碼短一些之外,完全不具有復用性和擴展性,因為ClothesPage下的所有Component都只能為Clothes服務了。而其他每個概念都必須把這一切重復一遍。

如果走入另一種極端呢,抽象出一種萬用Component,只要傳入一個大而全的object,就可以渲染出任意的頁面。這個時候雖然復用性有了,但是你會發現你什么也沒做,因為這個Component就是HTML的另一層封裝,那些傳入的參數包含了所有數據,你需要把這些不同的數據同化。

歸根結底,Component架構的精髓在于多層,按照人類理解程度分層。否則永遠無法分清楚什么是數據,什么是樣式,因為它們只會在某一層中有劃分。混亂的分層只會導致架構回歸到傳統的MVC兩層結構中去。也因此,前端面向對象必須基于一層,脫離了某一層而論對象或類,都是可笑的,一個類,到了下一層可能就是一個實例。

 

來自:http://www.tych.io/tech/2017/02/17/frontend-architecture.html

 

 本文由用戶 TabathaMatt 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!