vue和react對比(詳解)
放兩張圖鎮壓小妖怪
本文先講共同之處,
再分析區別
大綱在此:
共同點:
a、都使用虛擬dom
b、提供了響應式和元件化的檢視元件
c、注意力集中保持在覈心庫,而將其他功能如路由和全域性狀態管理交給相關的庫。
區別:
a、優化
b、HTML&CSS
c、構建工具
d、數據系結
e、狀態管理
f、路由
g、渲染效能
h、數據更新
i、開發模式及規模
j、使用場景
k、伺服器端渲染(SSR)
l、擴充套件(高階元件和mixin)
1、都使用虛擬DOM
vue:Vue在2.0版本引入了vdom。其vdom是基於 snabbdom 庫所做的修改。snabbdom是一個開源的vdom庫。snabbdom的主要作用就是將傳入的JS模擬的DOM結構轉換成虛擬的DOM節點。先通過其中的 h函數 將JS模擬的DOM結構轉換成虛擬DOM之後,再通過其中的 patch函數 將虛擬DOM轉換成真實的DOM渲染到頁面中。爲了保證頁面的最小化渲染,snabbdom引入了 Diff演算法 ,通過Diff演算法找出前後兩個虛擬DOM之間的差異,只更新改變了的DOM節點,而不重新渲染爲改變的DOM節點。
複製程式碼
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title></head><body>
<p id="container"></p>
<button id="btn-change">change</button>
<!-- 引入snabbdom庫,先不必糾結爲什麼這樣引入,以及每個檔案的作用。 -->
<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-class.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-props.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-style.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.1/snabbdom-eventlisteners.js"></script>
<script src="https://cdn.bootcss.com/snabbdom/0.7.1/h.js"></script>
<script>
//定義patch函數
var patch = snabbdom.init([
snabbdom_class,
snabbdom_props,
snabbdom_style,
snabbdom_eventlisteners
]) //定義h函數
var h = snabbdom.h; //生成一個vnode
var vnode = h('ul#list',{},[
h('li.item',{},['Item 1']),
h('li.item',{},['Item 2']),
])
//console.log(vnode);
//獲取container
var container = document.getElementById('container');
patch(container,vnode);//初次渲染
var btn = document.getElementById('btn-change');
btn.onclick = function() {
var newVnode = h('ul#list',{},[
h('li.item',{},['Item 1']),
h('li.item',{},['Item B']),
h('li.item',{},['Item 3']),
])
patch(vnode,newVnode);//再次渲染
vnode = newVnode;//將修改後的newVnode賦值給vnode
}
</script>
</body>
</html>
複製程式碼
vue中的模板解析和渲染的核心就是:通過類似snabbdom的h()和patch()的函數,先將模板解析成vnode,如果是初次渲染,則通過patch(container,vnode)將vnode渲染至頁面,如果是二次渲染,則通過patch(vnode,newVnode),先通過Diff演算法比較原vnode和newVnode的差異,以最小的代價重新渲染頁面。
react:react定義的一種類似於XML的JS擴充套件語法:XML+JS。
作用:用來建立react虛擬DOM(元素)物件。
複製程式碼
//使用虛擬DOM
import React from ‘react’
import ReactDOM from ‘react-dom’
import App from ‘./App’
import { BrowserRouter } from ‘react-router-dom’
import { Provider } from ‘react-redux’
import ‘styles/reset.css’
import ‘styles/animate.css’
import store from ‘./store’
ReactDOM.render(
,
document.getElementById(‘root’)
)
複製程式碼
2、都提供了響應式和元件化的檢視元件
3、都把注意力集中保持在覈心庫,而將其他功能如路由和全域性狀態管理交給相關的庫。(vue-router、vuex、react-router、redux等等)
4、優化
react:
在 React 應用中,當某個元件的狀態發生變化時,它會以該元件爲根,重新渲染整個元件子樹。
如要避免不必要的子元件的重渲染,
你需要在所有可能的地方使用 PureComponent,
或是手動實現 shouldComponentUpdate 方法。
react優化方法:
a、shouldComponentUpdate
b、immutable
可以看看:https://www.cnblogs.com/yangyangxxb/p/10104817.html
c、react-immutable-render-mixin,實現裝飾器簡化很多寫法
d、無狀態元件
e、高階元件
vue:
在 Vue 應用中,元件的依賴是在渲染過程中自動追蹤的,
所以系統能精確知曉哪個元件確實需要被重渲染。
你可以理解爲每一個元件都已經自動獲得了 shouldComponentUpdate,並且沒有上述的子樹問題限制。
Vue 的這個特點使得開發者不再需要考慮此類優化,從而能夠更好地專注於應用本身。
5、HTML&CSS
react:
在 React 中,一切都是 JavaScript。
在 React 中,所有的元件的渲染功能都依靠 JSX。
JSX 是使用 XML 語法編寫 JavaScript 的一種語法糖。
複製程式碼
import React, { Component } from ‘react’
import {
SearchContainer,
SearchContent
} from ‘./styledComponent.js’
import search from ‘images/search.png’
class Search extends Component {
render () {
return (
<SearchContent { …this.props }>
想吃什麼搜這裏,川菜
)
}
}
export default Search
複製程式碼
vue:
vue是把html,css,js組合到一起,用各自的處理方式
Vue 設定樣式的預設方法是單檔案元件裡類似 style 的標籤。
複製程式碼
複製程式碼
關於.vue檔案怎麼執行的可以看:
https://www.cnblogs.com/yangyangxxb/p/10094180.html
6、 構建工具
react:
構建:create-react-app 快速腳手架
複製程式碼
creat-react-app優點
無需設定:官方的設定堪稱完美,幾乎不用你再設定任何東西,就可以上手開發專案。
高整合性:整合了對React,JSX,ES6和Flow的支援。
自帶服務:整合了開發伺服器,你可以實現開發預覽一體化。
熱更新:儲存自動更新,讓你的開發更簡單。
全相容性:自動處理CSS的相容問題,無需新增-webkit字首。
自動發佈:整合好了發佈成品功能,編譯後直接發佈,並且包含了sourcemaps功能。
複製程式碼
npm install -g create-react-app
create-react-app my-app(自己的專案名稱)
cd my-app
npm start
vue:
構建:vue-cli腳手架
yarn global add @vue/cli (vue/cli是webpack的二次開發)
vue create 自定義專案名稱
7、數據系結
vue:vue是雙向系結, Vue.js 最核心的功能有兩個,一是響應式的數據系結系統,二是元件系統。所謂雙向系結,指的是vue範例中的data與其渲染的DOM元素的內容保持一致,無論誰被改變,另一方會相應的更新爲相同的數據。這是通過設定屬性存取器實現的。
Vue 的依賴追蹤是【原理上不支援雙向系結,v-model 只是通過監聽 DOM 事件實現的語法糖】
vue的依賴追蹤是通過 Object.defineProperty 把data物件的屬性全部轉爲 getter/setter來實現的;當改變數據的某個屬性值時,會觸發set函數,獲取該屬性值的時候會觸發get函數,通過這個特性來實現改變數據時改變檢視;也就是說只有當數據改變時纔會觸發檢視的改變,反過來在操作檢視時,只能通過DOM事件來改變數據,再由此來改變檢視,以此來實現雙向系結
雙向系結是在同一個元件內,將數據和檢視系結起來,和父子元件之間的通訊並無什麼關聯;
元件之間的通訊採用單向數據流是爲了元件間更好的解耦,在開發中可能有多個子元件依賴於父元件的某個數據,假如子元件可以修改父元件數據的話,一個子元件變化會引發所有依賴這個數據的子元件發生變化,所以vue不推薦子元件修改父元件的數據,直接修改props會拋出警告
思想是響應式的,也就是基於是數據可變的,通過對每一個屬性建立Watcher來監聽, 當屬性變化的時候,響應式的更新對應的虛擬dom
react:react是單向數據流;react中通過將state(Model層)與View層數據進行雙向系結達數據的實時更新變化,具體來說就是在View層直接寫JS程式碼Model層中的數據拿過來渲染,一旦像表單操作、觸發事件、ajax請求等觸發數據變化,則進行雙同步。推崇結合immutable來實現數據不可變。 可以看看:https://www.cnblogs.com/yangyangxxb/p/10104817.html。react在setState之後會重新走渲染的流程,如果shouldComponentUpdate返回的是true,就繼續渲染, 如果返回了false,就不會重新渲染,PureComponent就是重寫了shouldComponentUpdate, 然後在裏面作了props和state的淺層對比;
8、狀態管理
react:redux
可以看看:https://www.cnblogs.com/yangyangxxb/p/10047648.html
vue:vuex
可以看看:https://www.cnblogs.com/yangyangxxb/p/10096540.html
9、路由
可以直接看這個,很詳細react router @4 和 vue路由 詳解(全):https://www.cnblogs.com/yangyangxxb/p/10066650.html
10、渲染效能
react:
React 的渲染建立在 Virtual DOM 上——一種在記憶體中描述 DOM 樹狀態的數據結構。當狀態發生變化時,React 重新渲染 Virtual DOM,比較計算之後給真實 DOM 打修補程式。
Virtual DOM 提供了函數式的方法描述檢視,它不使用數據觀察機制 機製,每次更新都會重新渲染整個應用,因此從定義上保證了檢視與數據的同步。它也開闢了 JavaScript 同構應用的可能性。
在超大量數據的首屏渲染速度上,React 有一定優勢,因爲 Vue 的渲染機制 機製啓動時候要做的工作比較多,而且 React 支援伺服器端渲染。
元素是構成 React 應用的最小單位。元素用來描述你在螢幕上看到的內容,與瀏覽器的 DOM 元素不同,React 當中的元素事實上是普通的物件,React DOM 可以確保 瀏覽器 DOM 的數據內容與 React 元素保持一致。
我們用React 開發應用時一般只會定義一個根節點。但如果你是在一個已有的專案當中引入 React 的話,你可能會需要在不同的部分單獨定義 React 根節點。我們將 元素傳入一個名爲 ReactDOM.render() 的方法來將其渲染到頁面上,頁面上就會顯示該元素。
vue:
Vue 通過建立一個虛擬 DOM 對真實 DOM 發生的變化保持追蹤。
vue渲染的過程如下:
new Vue,執行初始化
掛載$mount方法,通過自定義Render方法、template、el等生成Render函數
通過Watcher監聽數據的變化
當數據發生變化時,Render函數執行生成VNode物件
通過patch方法,對比新舊VNode物件,通過DOM Diff演算法,新增、修改、刪除真正的DOM元素
11、數據更新
react:
React 元素都是immutable 不可變的。當元素被建立之後,你是無法改變其內容或屬性的。一個元素就好像是動畫裡的一幀,它代表應用介面在某一時間點的樣子。
根據我們現階段瞭解的有關 React 知識,更新介面的唯一辦法是建立一個新的元素,然後將它傳入 ReactDOM.render() 方法
vue:
數據直接修改,響應式。
12、開發模式及規模
react:
React本身,是嚴格的view層,MVC模式
vue:
Vue是MVVM模式的一種方式實現
雖然沒有完全遵循 MVVM 模型,Vue 的設計無疑受到了它的啓發。因此在文件中經常會使用 vm (ViewModel 的簡稱) 這個變數名錶示 Vue 範例。
13、使用場景
react:
a、構建一個大型應用專案
同時用Vue和React實現的簡單應用程式,可能會讓一個開發者潛意識中更加傾向於Vue。這是因爲基於模板的應用程式第一眼看上去更加好理解,而且能很快跑起來。
但是這些好處引入的技術債會阻礙應用擴充套件到更大的規模。
模板容易出現很難注意到的執行時錯誤,同時也很難去測試,重構和分解。
相比之下,Javascript模板可以組織成具有很好的分解性和幹(DRY)程式碼的元件,幹程式碼的可重用性和可測試性更好。
Vue也有元件系統和渲染函數,但是React的渲染系統可設定性更強,還有諸如淺(shallow)渲染的特性,和React的測試工具結合起來使用,使程式碼的可測試性和可維護性更好。
與此同時,React的immutable應用狀態可能寫起來不夠簡潔,但它在大型應用中意義非凡,因爲透明度和可測試性在大型專案中變得至關重要。
b、同時適用於Web端和原生APP
React Native是一個使用Javascript構建行動端原生應用程式(iOS,Android)的庫。 它與React.js相同,只是不使用Web元件,而是使用原生元件。 如果你學過React.js,很快就能上手React Native,反之亦然。
它的意義在於,開發者只需要一套知識和工具就能開發Web應用和行動端原生應用。如果你想同時做Web端開發和行動端開發,React爲你準備了一份大禮。
阿裡的Weex也是一個跨平臺UI專案,目前它以Vue爲靈感,使用了許多相同的語法,同時計劃在未來完全整合Vue,然而整合的時間和細節還不清楚。因爲Vue將HTML模板作爲它設計的核心部分,並且現有特性不支援自定義渲染,因此很難看出目前的Vue.js的跨平臺能力能像React和React Native一樣強大。
vue:
a、期待模板搭建應用
Vue應用的預設選項是把markup放在HTML檔案中。數據系結表達式採用的是和Angular相似的mustache語法,而指令(特殊的HTML屬性)用來向模板新增功能。
相比之下,React應用不使用模板,它要求開發者藉助JSX在JavaScript中建立DOM。
b、期待應用盡可能的小和快
當應用程式的狀態改變時,React和Vue都將構建一個虛擬DOM並同步到真實DOM中。 兩者都有各自的方法優化這個過程。
Vue核心開發者提供了一個benchmark測試,可以看出Vue的渲染系統比React的更快。測試方法是10000個專案的列表渲染100次。
從實用的觀點來看,這種benchmark只和邊緣情況有關,大部分應用程式中不會經常進行這種操作,所以這不應該被視爲一個重要的比較點。
但是,頁面大小是與所有專案有關的,這方面Vue再次領先,它目前的版本壓縮後只有25.6KB。
React要實現同樣的功能,你需要React DOM(37.4KB)和React with Addon庫(11.4KB),共計44.8KB,幾乎是Vue的兩倍大。
雙倍的體積並不能帶來雙倍的功能。
14、伺服器端渲染(SSR)
用戶端渲染路線:1. 請求一個html -> 2. 伺服器端返回一個html -> 3. 瀏覽器下載html裏面的js/css檔案 -> 4. 等待js檔案下載完成 -> 5. 等待js載入並初始化完成 -> 6. js程式碼終於可以執行,由js程式碼向後端請求數據( ajax/fetch ) -> 7. 等待後端數據返回 -> 8. react-dom( 用戶端 )從無到完整地,把數據渲染爲響應頁面
伺服器端渲染路線:1. 請求一個html -> 2. 伺服器端請求數據( 內網請求快 ) -> 3. 伺服器初始渲染(伺服器端效能好,較快) -> 4. 伺服器端返回已經有正確內容的頁面 -> 5. 用戶端請求js/css檔案 -> 6. 等待js檔案下載完成 -> 7. 等待js載入並初始化完成 -> 8. react-dom( 用戶端 )把剩下一部分渲染完成( 內容小,渲染快 )
react:
React的虛擬DOM是其可被用於伺服器端渲染的關鍵。首先每個ReactComponent 在虛擬DOM中完成渲染,然後React通過虛擬DOM來更新瀏覽器DOM中產生變化的那一部分,虛擬DOM作爲記憶體中的DOM表現,爲React在Node.js這類非瀏覽器環境下的吮吸給你提供了可能,React可以從虛擬DoM中生成一個字串。而不是跟新真正的DOM,這使得我們可以在用戶端和伺服器端使用同一個React Component。
React 提供了兩個可用於伺服器端渲染元件的函數:React.renderToString 和React.render-ToStaticMarkup。 在設計用於伺服器端渲染的
ReactComponent時需要有預見性,考慮以下方面。
選取最優的渲染函數。
如何支援元件的非同步狀態。
如何將應用的初始化狀態傳遞到用戶端。
哪些生命週期函數可以用於伺服器端的渲染。
如何爲應用提供同構路由支援。
單例、範例以及上下文的用法。
vue:
Vue.js 是構建用戶端應用程式的框架。預設情況下,可以在瀏覽器中輸出 Vue 元件,進行生成 DOM 和操作 DOM。然而,也可以將同一個元件渲染爲伺服器端的 HTML 字串,將它們直接發送到瀏覽器,最後將靜態標記」混合」爲用戶端上完全互動的應用程式。
伺服器渲染的 Vue.js 應用程式也可以被認爲是」同構」或」通用」,因爲應用程式的大部分程式碼都可以在伺服器和用戶端上執行。
伺服器端渲染優勢
15、擴充套件(高階元件和mixin)
react可以通過高階元件(Higher Order Components–HOC)來擴充套件,而vue需要通過mixins來擴充套件
React剛開始也有mixin的寫法,通過React.createClass的api,不過現在很少用了。
Vue也不是不能實現高階元件,只是特別麻煩,因爲Vue對與元件的option做了各種處理, 想實現高階元件就要知道每一個option是怎麼處理的,然後正確的設定。
mixin小介紹:
vue中提供了一種混合機制–mixins,用來更高效的實現元件內容的複用。最開始我一度認爲這個和元件好像沒啥區別。。後來發現錯了。下面 下麪我們來看看mixins和普通情況下引入元件有什麼區別?
元件在參照之後相當於在父元件內開闢了一塊單獨的空間,來根據父元件props過來的值進行相應的操作,單本質上兩者還是涇渭分明,相對獨立。
而mixins則是在引入元件之後,則是將元件內部的內容如data等方法、method等屬性與父元件相應內容進行合併。相當於在引入後,父元件的各種屬性方法都被擴充了。
單純元件參照:
父元件 + 子元件 >>> 父元件 + 子元件
mixins:
父元件 + 子元件 >>> new父元件
作用:多個元件可以共用數據和方法,在使用mixin的元件中引入後,mixin中的方法和屬性也就併入到該元件中,可以直接使用。勾點函數會兩個都被呼叫,mixin中的勾點首先執行。
下面 下麪給大家介紹vue mixin的用法,具體介紹如下所示:
複製程式碼
//mixin.js
export default {
data() {
return {
name: ‘mixin’
}
},
created() {
console.log(‘mixin…’, this.name);
},
mounted() {},
methods: {}
}
複製程式碼
使用:
vue檔案中使用
import ‘@/mixin’; // 引入mixin檔案
export default {
mixins: [mixin]
}
小結
總結一下,我們發現,
Vue的優勢包括:
模板和渲染函數的彈性選擇
簡單的語法及專案建立
更快的渲染速度和更小的體積
React的優勢包括:
更適用於大型應用和更好的可測試性
同時適用於Web端和原生App
更大的生態圈帶來的更多支援和工具
而實際上,React和Vue都是非常優秀的框架,它們之間的相似之處多過不同之處,並且它們大部分最棒的功能是相通的:
利用虛擬DOM實現快速渲染
輕量級
響應式和元件化
伺服器端渲染
易於整合路由工具,打包工具以及狀態管理工具
優秀的支援和社羣
複製程式碼
參考1:https://blog.csdn.net/CystalVon/article/details/78428036
參考2:https://cn.vuejs.org/v2/guide/comparison.html
參考3:https://www.cnblogs.com/suihang/p/10098860.html
參考4:https://www.jb51.net/article/138757.htm