1. 程式人生 > 其它 >理解Vue和React區別

理解Vue和React區別

理解Vue和React區別

Vue和React相同點非常多:

  1. 都使用Virtural DOM

  2. 都使用元件化思想,流程基本一致

  3. 都是響應式,推崇單向資料流

  4. 都有成熟的社群,都支援服務端渲染

Vue和React實現原理和流程基本一致,都是使用Virtual DOM + Diff演算法。不管是Vue的template模板 + options api寫法,還是React的Class或者Function(js 的class寫法也是function函式的一種)寫法,底層最終都是為了生成render函式,render函式執行返回VNode(虛擬DOM的資料結構,本質上是棵樹)。當每一次UI更新時,總會根據render重新生成最新的VNode,然後跟以前快取起來老的VNode進行比對,再使用Diff演算法(框架核心)去真正更新真實DOM(虛擬DOM是JS物件結構,同樣在JS引擎中,而真實DOM在瀏覽器渲染引擎中,所以操作虛擬DOM比操作真實DOM開銷要小的多)。

Vue和React通用流程:vue template/react jsx -> render函式 -> 生成VNode -> 當有變化時,新老VNode diff -> diff演算法對比,並真正去更新真實DOM。

核心還是Virtual DOM,為什麼Vue和React都選擇Virtual DOM(React首創VDOM,Vue2.0開始引入VDOM)?,個人認為主要有以下幾點:

  1. 減少直接操作DOM。框架給我們提供了遮蔽底層dom書寫的方式,減少頻繁的整更新dom,同時也使得資料驅動檢視

  2. 為函式式UI程式設計提供可能(React核心思想)

  3. 可以跨平臺,渲染到DOM(web)之外的平臺。比如ReactNative,Weex

以下重點說下兩者不同的點。

#1. 核心思想不同

Vue早期定位是儘可能的降低前端開發的門檻(這跟Vue作者是獨立開發者也有關係)。所以Vue推崇靈活易用(漸進式開發體驗),資料可變,雙向資料繫結(依賴收集)

React早期口號是Rethinking Best Practices。背靠大公司Facebook的React,從開始起就不缺關注和使用者,而且React想要做的是用更好的方式去顛覆前端開發方式(事實上跟早期jquery稱霸前端,的確是顛覆了)。所以React推崇函數語言程式設計(純元件),資料不可變以及單向資料流。函數語言程式設計最大的好處是其穩定性(無副作用)和可測試性(輸入相同,輸出一定相同),所以通常大家說的React適合大型應用,根本原因還是在於其函數語言程式設計。

由於兩者核心思想的不同,所以導致Vue和React許多外在表現不同(從開發層面看)

#1.1 核心思想不同導致寫法差異

Vue推崇template(簡單易懂,從傳統前端轉過來易於理解)、單檔案vue。而且雖然Vue2.0以後使用了Virtual DOM,使得Vue也可以使用JSX(bebel工具轉換支援),但Vue官方依然首先推薦template,這跟Vue的核心思想和定位有一定關係。

React推崇JSX、HOC、all in js

#1.2 核心思想不同導致api差異

Vue定位簡單易上手,基於template模板 + options API,所以不可避免的有較多的概念和api。比如template模板中需要理解slot、filter、指令等概念和api,options API中需要理解watch、computed(依賴收集)等概念和api。

React本質上核心只有一個Virtual DOM + Diff演算法,所以API非常少,知道setState就能開始開發了。

#1.3 核心思想不同導致社群差異

由於Vue定義簡單易上手,能快速解決問題,所以很多常見的解決方案,是Vue官方主導開發和維護。比如狀態管理庫Vuex、路由庫Vue-Router、腳手架Vue-CLI、Vutur工具等。屬於那種大包大攬,遇到某類通用問題,只需要使用官方給出的解決方案即可。

React只關注底層,上層應用解決方案基本不插手,連最基礎的狀態管理早期也只是給出flow單向資料流思想,大部分都丟給社群去解決。比如狀態管理庫方面,有redux、mobx、redux-sage、dva等一大堆(選擇困難症犯了),所以這也造就了React社群非常繁榮。同時由於有社群做上層應用解決方案,所以React團隊有更多時間專注於底層升級,比如花了近2年時間把底層架構改為Fiber架構,以及創造出React Hooks來替換HOC,Suspense等。 更多框架設計思想可看 尤雨溪 - 在框架設計中尋求平衡 (opens new window)

#1.4 核心思想不同導致未來升級方向不同

核心思想不同,決定了Vue和React未來不管怎麼升級變化,Vue和React考慮的基本盤不變。

Vue依然會定位簡單易上手(漸進式開發),依然是考慮通過依賴收集來實現資料可變。這點從Vue3核心更新內容可以看到:template語法基本不變、options api只增加了setup選項(composition api)、基於依賴收集(Proxy)的資料可變。更多Vue3具體更新內容可看筆者總結 Vue3設計思想 (opens new window)或者 尤雨溪 - 聊聊 Vue.js 3.0 Beta 官方直播 (opens new window)

React的函數語言程式設計這個基本盤不會變。React核心思想,是把UI作為Basic Type,比如String、Array型別,然後經過render處理,轉換為另外一個value(純函式)。從React Hooks可以看出,React團隊致力於元件函數語言程式設計,(純元件,無class元件),儘量減少副作用(減少this,this會引起副作用)。

#2. 元件實現不同

Vue原始碼實現是把options掛載到Vue核心類上,然後再new Vue({options})拿到例項(vue元件的script匯出的是一個掛滿options的純物件而已)。所以options api中的this指向內部Vue例項,對使用者是不透明的,所以需要文件去說明this.$slot、this.$xxx這些api。另外Vue外掛都是基於Vue原型類基礎之上建立的,這也是Vue外掛使用Vue.install的原因,因為要確保第三方庫的Vue和當前應用的Vue物件是同一個。

React內部實現比較簡單,直接定義render函式以生成VNode,而React內部使用了四大元件類包裝VNode,不同型別的VNode使用相應的元件類處理,職責劃分清晰明瞭(後面的Diff演算法也非常清晰)。React類元件都是繼承自React.Component類,其this指向使用者自定義的類,對使用者來說是透明的。

地址 https://user-images.githubusercontent.com/6310131/58312027-04ca9180-7e3d-11e9-9099-786694da7c38.png

#3. 響應式原理不同

這個問題網上已經有許多優秀文章都詳細講解過,這裡就不具體展開講,對Vue3響應式原理有興趣可以看筆者 Vue3響應式原理 (opens new window)(Vue2和Vue3響應式原理基本一致,都是基於依賴收集,不同的是Vue3使用Proxy)。

Vue

  • Vue依賴收集,自動優化,資料可變。

  • Vue遞迴監聽data的所有屬性,直接修改。

  • 當資料改變時,自動找到引用元件重新渲染。

React

  • React基於狀態機,手動優化,資料不可變,需要setState驅動新的State替換老的State。

  • 當資料改變時,以元件為根目錄,預設全部重新渲染

#4. diff演算法不同

兩者流程思維上是類似的,都是基於兩個假設(使得演算法複雜度降為O(n)):

  1. 不同的元件產生不同的 DOM 結構。當type不相同時,對應DOM操作就是直接銷燬老的DOM,建立新的DOM。

  2. 同一層次的一組子節點,可以通過唯一的 key 區分。

但兩者原始碼實現上有區別:

Vue基於snabbdom庫,它有較好的速度以及模組機制。Vue Diff使用雙向連結串列,邊對比,邊更新DOM。

React主要使用diff佇列儲存需要更新哪些DOM,得到patch樹,再統一操作批量更新DOM

地址 https://user-images.githubusercontent.com/6310131/58315009-41998700-7e43-11e9-8c52-438adad9b23b.png

#5. 事件機制不同

Vue

  • Vue原生事件使用標準Web事件

  • Vue元件自定義事件機制,是父子元件通訊基礎

  • Vue合理利用了snabbdom庫的模組外掛

React

  • React原生事件被包裝,所有事件都冒泡到頂層document監聽,然後在這裡合成事件下發。基於這套,可以跨端使用事件機制,而不是和Web DOM強繫結。

  • React元件上無事件,父子元件通訊使用props

#Vue 和 React原始碼流程圖

#Vue整體流程圖

地址 https://user-images.githubusercontent.com/6310131/58315972-1dd74080-7e45-11e9-94bc-b494d41ae61c.png

#React整體流程圖

地址 https://user-images.githubusercontent.com/6310131/58316112-6b53ad80-7e45-11e9-8b2a-d31bfaf269aa.png