關於新框架的學習

發表於2016-01-30

這是對知乎上一個問題的回答:https://www.zhihu.com/question/39943474/answer/83905933

我們學一個東西,通常兩個目的:

  • 為了解決現有的問題
  • 為了解決將來可能會有的問題

所以,在學這些東西之前,先必須瞭解,它們是用來解決什麼問題的。

Angular,React,Vue,這三者其實面對的是同一個領域,那就是Web應用,什麼是Web應用呢,我之前有一篇大致講了:構建單頁Web應用 · Issue #5 · xufei/blog · GitHub

這三者中,Angular的適用領域相對窄一些,React可以擴充到服務端,移動端Native部分,而Vue因為比較輕量,還能用於業務場景非常輕的頁面中。

在Web應用中,我們需要解決的問題可以歸納為三類:

  • 狀態
  • 組織
  • 效率
  1. 狀態

什麼是狀態?

在一個業務介面中,我們可能會根據某些資料去生成一塊介面,然後通過介面上的某些操作,改變一些資料,從而影響介面的另外一些部分。

這裡面就存在兩種關係,一種是從資料到介面,一種是從介面到資料。能夠描述介面當前狀況的資料,就可以被稱為狀態。

如果不對狀態作抽象,很可能會導致邏輯的混亂,比如說,一個地方點了,要改多個地方,這種程式碼直接寫,很容易寫亂的,所以,不同的框架採用不同的方式進行了處理。

比如說MVVM流的Angular和Vue,還有Avalon,Regular,Knockout,都是走的這一流派,通過類似模板的語法,描述介面狀態與資料的繫結關係,然後通過內部轉換,把這個結構建立起來,當介面發生變化的時候,按照配置規則去更新相應的資料,然後,再根據配置好的規則去,從資料更新介面狀態。

React走的是另外一個流派,就是所謂的函式式,在這個裡面,推崇的是單向資料流:給定原始介面(或資料),施加一個變化,就能推匯出另外一個狀態(介面或者資料的更新)。

在這裡需要額外提一下ReactiveJS,它的理念又有所不同,是基於Reactive的。

  1. 組織

剛才這些,都可以看作是滿足最基本的需求,那就是業務的正確性。在這之後,就有另外的訴求了,首當其衝的就是整個業務程式碼的組織。

所謂組織,指的是兩個方面,一方面是模組關係,另一方面是業務模型。

我們是怎樣解決模組關係的呢?共識就是元件化。整個應用形成倒置的元件樹,每個元件提供對外介面,然後內部只關注自己的實現。這些東西說起來簡單,但實際做的時候還是有非常多需要考慮的東西,包括元件的定義,約束,管理,測試等等,而在Web這個體系中,元件化也有一些不太適合的場景,需要做一些權衡,這方面詳細說就比較複雜了,需要好多篇幅才能說清楚,可以看看我這篇:Web應用元件化的權衡 · Issue #22 · xufei/blog · GitHub

那麼,業務模型又是指什麼呢?我們提到React的時候,就會聽到Flux,Redux之類的東西,為什麼又要有它們呢?我們必須認識到,脫離了這類東西,純上層的元件化是不牢固的,如果你感受不到,只有一個原因:你的專案的業務層太薄。

業務模型指的是所處領域中的業務資料、規則、流程的集合。即使拋開所有展示層,這一層也是應當要能夠運作起來的。

那麼,這跟Redux之類又有什麼關係呢?

我們剛才提到元件化,整個應用形成了一個元件樹,元件之間可能會需要通訊,它們通訊的內容可能是簡單的介面事件,也可能是業務含義較深,能夠牽一髮而動全身的。介面是怎麼來的?是由初始介面加上狀態形成的,為了能夠反映介面的變化,我們必須使得對業務模型的每一個擾動都收斂到確切的狀態,所以,這也就是Redux這類東西的意義所在。

所以,沒有Redux之類輔助方案的React,是不完整的。而Redux本身,也不是侷限到只能作為React輔助方案的,它的理念,對於Angular,Vue,照樣是非常重要的補充。在同一業務場景下,對於每個框架來說,資料模型層面臨的問題都是一樣的,在這一層並沒有任何分別。

另外,Angular 2中引入了RxJS,這個東西處理這方面也是有很大優勢的。

在這裡我要插一句自己的想法,很多學習能力較強的朋友,當他發現FP,FRP之類程式設計模型的時候,會非常喜歡,但對於大型專案,需要很多人協作的狀況來說,不一定是好事。

用程式導向,物件導向的那些方式,雖然笨重,但好處是門檻低,符合大多數人的理解和思維方式,並且可以複用幾十年積累的各種設計模式和經驗。所以,如果不是小而精悍的團隊,我對引入FP和FRP都是比較保守的。

在這些東西下層,還有Relay,GraphQL等等致力於業務模型同步的方案,但這個引入代價同樣是非常大。

再插另外一句:很多人吐槽Angular大而全笨重,吐槽React全家桶,但其實世界上大部分人是沒有框架整合能力的,小而美的庫最後整合了,在面臨各種業務需求之後不斷引入新模組,也還是一個大而全的方案。在絕大部分場景下,還是有一整套標配模組比較好。你看ExtJS他也單獨提供ExtCore模組,但不但競爭不過jQuery,連mootools和prototype都競爭不過,用它的人幾乎都是用全方案的。

  1. 效率

效率也分兩種,一種是開發效率,一種是執行效率。

我們前面提到,元件化,這是提升開發效率的一種手段,在元件化這個點上,各路框架的組織方式大同小異,反正最終都是元件樹。

具體到單個元件的實現上,我個人是傾向於MVVM流的,之前 @題葉 做過對比,MVVM系的程式碼量會少一些,開發效率稍高一點。

其中,Angular因為實現的特殊性,有作用域繼承之類的雙刃劍黑魔法,開發效率的不穩定因素要高不少,深刻理解的人用起來效率很高,不理解的用了到處是坑。

再看執行效率,這裡面,Angular是較低的那個,主要在於資料變更檢測方式,但這也不是絕對的,在部分場景下,髒檢測未必就沒有優勢,這個記得 @鄭海波論述過。

執行效率的另外一面主要是建立和修改DOM,在建立上,大家是沒有太大差異的,而在修改DOM的時候,React首創的虛擬DOM有很大優勢,所以其他框架內部實現也在逐漸借鑑。

(我之前有個對虛擬DOM的回答是有偏差的,稍後去更新)

^^^^^^^^^^^^^^^^^^^^^^^^^^^

如果看到這裡,很可能你會疑惑,題目問的明明是學哪個好,我說這些是什麼意思?

我用這些篇幅說明了Web應用的業務開發中存在哪些麻煩,每種技術又是來解決什麼痛點的,這樣,你可以按照自己的需求去,結合業務場景進行分析,然後選擇需要的挨個學下去。

其實學API之類的很快,還是要把自己業務中的難點想清楚,帶著問題去學,帶著需求去學,學思想重於學使用,一定能事半功倍。

相關文章