
vue or react?That's a question.

前言
近兩年前端技術(shù)層出不窮,目前市面上已經(jīng)有了很多供前端人員使用的開發(fā)框架,轉(zhuǎn)眼19年已過大半,前端框架領(lǐng)域日趨成熟,實現(xiàn)了三足鼎立的局面,react和vue勢頭強(qiáng)勁,在國內(nèi)發(fā)展迅速,形勢一片大好。
最近在學(xué)習(xí)使用框架的時候,分別使用vue和react開發(fā)了兩個移動端產(chǎn)品,對這兩個框架的學(xué)習(xí)曲線有了一些感悟,這兩個都是現(xiàn)在比較熱門的js框架,它倆在使用方式上和學(xué)習(xí)復(fù)雜度上還是有很大區(qū)別的,這里簡單總結(jié)下兩者的差異。
主要從以下幾個方面入手方面展開:
- 框架的誕生
- 設(shè)計思想
- 編寫語法
- 腳手架構(gòu)建工具
- 數(shù)據(jù)綁定
- 虛擬DOM
- 指令
- 性能優(yōu)化
- 原生渲染native
- ssr服務(wù)端渲染
- 生命周期函數(shù)
- 銷毀組件
- 狀態(tài)集管理工具
誕生
vue
vue由尤雨溪開發(fā),一開始是個人項目,現(xiàn)在有專門的技術(shù)團(tuán)隊進(jìn)行維護(hù)。vue近幾年來特別的受關(guān)注,三年前的時候angularJS霸占前端JS框架市場很長時間,接著react框架橫空出世,因為它有一個特性是虛擬DOM,從性能上碾軋angularJS,這個時候,vue1.0悄悄的問世了,它的優(yōu)雅,輕便也吸引了一部分用戶,開始受到關(guān)注,16年中旬,VUE2.0問世,不管從性能上,還是從成本上都隱隱超過了react,火的一塌糊涂,這個時候,angular開發(fā)團(tuán)隊也開發(fā)了angular2.0版本,并且更名為angular,吸收了react、vue的優(yōu)點,加上angular本身的特點,也吸引到很多用戶,目前已經(jīng)迭代到5.0了。友情提示注意下vue的誕生時間,如果正好有小伙伴在面試,被問到你是從什么時候開始接觸并且使用vue的,你要是回答用了5、6年了那場面就十分尷尬了。
react
起初facebook在建設(shè)instagram(圖片分享)的時候,因為牽扯到一個東西叫數(shù)據(jù)流,那為了處理數(shù)據(jù)流并且還要考慮好性能方面的問題,F(xiàn)acebook開始對市場上的各種前端MVC框架去進(jìn)行一個研究,然而并沒有看上眼的,于是Facebook覺得,還是自己開發(fā)一個才是最棒的,那么他們決定拋開很多所謂的“最佳實踐”,重新思考前端界面的構(gòu)建方式,他們就自己開發(fā)了一套,果然大牛創(chuàng)造力還是很強(qiáng)大的。
React 起源于 Facebook 的內(nèi)部項目,因為該公司對市場上所有 JavaScript MVC 框架,都不滿意,就決定自己寫一套,用來架設(shè)Instagram 的網(wǎng)站。做出來以后,發(fā)現(xiàn)這套東西很好用,就在2013年5月開源了。
設(shè)計思想
vue
vue的官網(wǎng)中說它是一款漸進(jìn)式框架,采用自底向上增量開發(fā)的設(shè)計。這里我們需要明確一個概念,什么是漸進(jìn)式框架。在聲明式渲染(視圖模板引擎)的基礎(chǔ)上,我們可以通過添加組件系統(tǒng)(components)、客戶端路由(vue-router)、大規(guī)模狀態(tài)管理(vuex)來構(gòu)建一個完整的框架。Vue從設(shè)計角度來講,雖然能夠涵蓋所有這些內(nèi)容,但是你并不需要一上手就把所有東西全用上,因為沒有必要。無論從學(xué)習(xí)角度,還是實際情況,這都是可選的。聲明式渲染和組建系統(tǒng)是Vue的核心庫所包含內(nèi)容,而客戶端路由、狀態(tài)管理、構(gòu)建工具都有專門解決方案。這些解決方案相互獨立,你可以在核心的基礎(chǔ)上任意選用其他的部件,不一定要全部整合在一起??梢钥吹?,所說的“漸進(jìn)式”,其實就是Vue的使用方式,同時也體現(xiàn)了Vue的設(shè)計的理念。
react
react主張函數(shù)式編程,所以推崇純組件,數(shù)據(jù)不可變,單向數(shù)據(jù)流,當(dāng)然需要雙向的地方也可以手動實現(xiàn),比如借助 onChange 和 setState 來實現(xiàn)一個雙向的數(shù)據(jù)流。而vue是基于可變數(shù)據(jù)的,支持雙向綁定,它提供了v-model這樣的指令來實現(xiàn)文本框的數(shù)據(jù)流雙向綁定。
編寫語法
vue
vue推薦的做法是webpack+vue-loader的單文件組件格式,vue保留了html、css、js分離的寫法,使得現(xiàn)有的前端開發(fā)者在開發(fā)的時候能保持原有的習(xí)慣,更接近常用的web開發(fā)方式,模板就是普通的html,數(shù)據(jù)綁定使用mustache風(fēng)格,樣式直接使用css。其中<style>標(biāo)簽還提供了一個可選的scoped屬性,它會為組件內(nèi) CSS 指定作用域,用它來控制僅對當(dāng)前組件有效還是全局生效。
模板和JSX是各有利弊的東西。模板更貼近我們的HTML,可以讓我們更直觀地思考語義結(jié)構(gòu),更好地結(jié)合CSS的書寫。
同時vue也支持JSX語法,因為是真正的JavaScript,擁有這個語言本身的所有的能力,可以進(jìn)行復(fù)雜的邏輯判斷,進(jìn)行選擇性的返回最終要返回的DOM結(jié)構(gòu),能夠?qū)崿F(xiàn)一些在模板的語法限制下,很難做到的一些事情。
react
用過react的開發(fā)者可能知道,react是沒有模板的,直接就是一個渲染函數(shù),它中間返回的就是一個虛擬DOM樹,React推薦的做法是 JSX + inline style, 也就是把HTML和CSS全都寫進(jìn)JavaScript了,即'all in js'。JSX實際就是一套使用XML語法,用于讓我們更簡單地去描述樹狀結(jié)構(gòu)的語法糖。在react中,所有的組件的渲染功能都依靠JSX。你可以在render()中編寫類似XML的語法,它最終會被編譯成原生JavaScript。不僅僅是 HTML 可以用 JSX 來表達(dá),現(xiàn)在的潮流也越來越多地將 CSS 也納入到 JavaScript 中來處理。JSX是基于 JS 之上的一套額外語法,學(xué)習(xí)使用起來有一定的成本。
構(gòu)建工具
vue
vue提供了CLI 腳手架,可以幫助你非常容易地構(gòu)建項目。全局安裝之后,我們就可以用 vue create命令創(chuàng)建一個新的項目,vue 的 CLI 跟其他 CLI不同之處在于,有多個可選模板,有簡單的也有復(fù)雜的,可以讓用戶自定義選擇需要安裝的模塊,還可以將你的選擇保存成模板,便于后續(xù)使用。
極簡的配置,更快的安裝,可以更快的上手。它也有一個更完整的模板,包括單元測試在內(nèi)的各種內(nèi)容都涵蓋,但是,它的復(fù)雜度也更高,這又涉及到根據(jù)用例來選擇恰當(dāng)復(fù)雜度的問題。
react
React 在這方面也提供了 create-react-app,但是現(xiàn)在還存在一些局限性:
- 它不允許在項目生成時進(jìn)行任何配置,而 Vue CLI 運行于可升級的運行時依賴之上,該運行時可以通過插件進(jìn)行擴(kuò)展。
- 它只提供一個構(gòu)建單頁面應(yīng)用的默認(rèn)選項,而 Vue 提供了各種用途的模板。
- 它不能用用戶自建的預(yù)設(shè)配置構(gòu)建項目,這對企業(yè)環(huán)境下預(yù)先建立約定是特別有用的。
而要注意的是這些限制是故意設(shè)計的,這有它的優(yōu)勢。例如,如果你的項目需求非常簡單,你就不需要自定義生成過程。你能把它作為一個依賴來更新。
數(shù)據(jù)綁定
vue
vue是實現(xiàn)了雙向數(shù)據(jù)綁定的mvvm框架,當(dāng)視圖改變更新模型層,當(dāng)模型層改變更新視圖層。在vue中,使用了雙向綁定技術(shù),就是View的變化能實時讓Model發(fā)生變化,而Model的變化也能實時更新到View。
Vue采用數(shù)據(jù)劫持&發(fā)布-訂閱模式的方式,vue在創(chuàng)建vm的時候,會將數(shù)據(jù)配置在實例當(dāng)中,然后通過Object.defineProperty對數(shù)據(jù)進(jìn)行操作,為數(shù)據(jù)動態(tài)添加了getter與setter方法,當(dāng)獲取數(shù)據(jù)的時候會觸發(fā)對應(yīng)的getter方法,當(dāng)設(shè)置數(shù)據(jù)的時候會觸發(fā)對應(yīng)的setter方法,從而進(jìn)一步觸發(fā)vm的watcher方法,然后數(shù)據(jù)更改,vm則會進(jìn)一步觸發(fā)視圖更新操作。
react
react是單向數(shù)據(jù)流,react中屬性是不允許更改的,狀態(tài)是允許更改的。react中組件不允許通過this.state這種方式直接更改組件的狀態(tài)。自身設(shè)置的狀態(tài),可以通過setState來進(jìn)行更改。在setState中,傳入一個對象,就會將組件的狀態(tài)中鍵值對的部分更改,還可以傳入一個函數(shù),這個回調(diào)函數(shù)必須向上面方式一樣的一個對象函數(shù)可以接受prevState和props。通過調(diào)用this.setState去更新this.state,不能直接操作this.state,請把它當(dāng)成不可變的。
調(diào)用setState更新this.state,它不是馬上就會生效的,它是異步的。所以不要認(rèn)為調(diào)用完setState后可以立馬獲取到最新的值。多個順序執(zhí)行的setState不是同步的一個接著一個的執(zhí)行,會加入一個異步隊列,然后最后一起執(zhí)行,即批處理。
setState是異步的,導(dǎo)致獲取dom可能拿的還是之前的內(nèi)容,所以我們需要在setState第二個參數(shù)(回調(diào)函數(shù))中獲取更新后的新的內(nèi)容。
diff算法
vue
vue中diff算法實現(xiàn)流程
在內(nèi)存中構(gòu)建虛擬dom樹
將內(nèi)存中虛擬dom樹渲染成真實dom結(jié)構(gòu)
數(shù)據(jù)改變的時候,將之前的虛擬dom樹結(jié)合新的數(shù)據(jù)生成新的虛擬dom樹
將此次生成好的虛擬dom樹和上一次的虛擬dom樹進(jìn)行一次比對(diff算法進(jìn)行比對),來更新只需要被替換的DOM,而不是全部重繪。在Diff算法中,只平層的比較前后兩棵DOM樹的節(jié)點,沒有進(jìn)行深度的遍歷。
會將對比出來的差異進(jìn)行重新渲染
react
react中diff算法實現(xiàn)流程
- DOM結(jié)構(gòu)發(fā)生改變-----直接卸載并重新create
- DOM結(jié)構(gòu)一樣-----不會卸載,但是會update變化的內(nèi)容
- 所有同一層級的子節(jié)點.他們都可以通過key來區(qū)分-----同時遵循1.2兩點
(其實這個key的存在與否只會影響diff算法的復(fù)雜度,換言之,你不加key的情況下,diff算法就會以暴力的方式去根據(jù)一二的策略更新,但是你加了key,diff算法會引入一些另外的操作)
React會逐個對節(jié)點進(jìn)行更新,轉(zhuǎn)換到目標(biāo)節(jié)點。而最后插入新的節(jié)點,涉及到的DOM操作非常多。diff總共就是移動、刪除、增加三個操作,而如果給每個節(jié)點唯一的標(biāo)識(key),那么React優(yōu)先采用移動的方式,能夠找到正確的位置去插入新的節(jié)點。
vue會跟蹤每一個組件的依賴關(guān)系,不需要重新渲染整個組件樹。而對于React而言,每當(dāng)應(yīng)用的狀態(tài)被改變時,全部組件都會重新渲染,所以react中會需要shouldComponentUpdate這個生命周期函數(shù)方法來進(jìn)行控制。
指令
指令 (Directives) 是帶有 v- 前綴的特殊特性,指令的職責(zé)是,當(dāng)表達(dá)式的值改變時,將其產(chǎn)生的連帶影響,響應(yīng)式地作用于 DOM。
vue
vue中提供很多內(nèi)部指令供我們使用,它可以讓我們進(jìn)行一些模板的操作,例如有時候,我們的data中的存放的數(shù)據(jù)不是個簡單的數(shù)字或者字符串,而是數(shù)組Array類型,這個時候,我們要把數(shù)組的元素展示在視圖上,就需要用到vue提供的 v-for 指令,來實現(xiàn)列表的渲染。
react
因為react中沒有v-for指令,所以循環(huán)渲染的時候需要用到map()方法來渲染視圖,并且將符合條件的元素放入一個新數(shù)組返回。
性能優(yōu)化
vue
vue中的每個組件內(nèi)部自動實現(xiàn)了shouldComponentUpdate的優(yōu)化,在vue里面由于依賴追蹤系統(tǒng)的存在,當(dāng)任意數(shù)據(jù)變動的時,Vue的每一個組件都精確地知道自己是否需要重繪,所以并不需要手動優(yōu)化。用vue渲染這些組件的時候,數(shù)據(jù)變了,對應(yīng)的組件基本上去除了手動優(yōu)化的必要性。而在react中我們需要手動去優(yōu)化其性能,但是當(dāng)數(shù)據(jù)特別多的時候vue中的watcher也會特別多,從而造成頁面卡頓,所以一般數(shù)據(jù)比較多的大型項目會傾向于使用react。在react官網(wǎng)中,官方也建議我們使用React來構(gòu)建快速響應(yīng)的大型 Web 應(yīng)用程序。
react
當(dāng)props或state發(fā)生改變的時候會觸發(fā)shouldComponentUpdate生命周期函數(shù),它是用來控制組件是否被重新渲染的,如果它返回true,則執(zhí)行render函數(shù),更新組件;如果它返回false,則不會觸發(fā)重新渲染的過程。
有的時候我們希望它在更新之前,和之前的狀態(tài)進(jìn)行一個對比,這個時候我們就需要重寫shouldComponentUpdate來避免不必要的dom操作,對比當(dāng)前的props或state和更新之后的nextProps或nextState,返回true時 ,組件更新;返回false,則不會更新,節(jié)省性能。
shouldComponentUpdate(nextProps, nextState) {
if (this.props.a !== nextProps.a) {
return true;
}
if (this.state.b !== nextState.b) {
return true;
}
return false;
}
我們也可以創(chuàng)建一個繼承React.PureComponent的React組件,它自帶shouldComponentUpdate,可以對props進(jìn)行淺比較,發(fā)現(xiàn)更新之后的props與當(dāng)前的props一樣,就不會進(jìn)行render了。
class Test extends React.PureComponent{
constructor(props){
super(props);
}
render(){
return <div>hello...{this.props.a}</div>
}
}
由于React.PureComponent進(jìn)行的是淺比較,也就是說它只會對比原對象的值是否相同,當(dāng)我們的props或state為數(shù)組或者對象這種引用類型的時候,我們修改它的數(shù)值,由于數(shù)據(jù)引用指針沒有發(fā)生改變,所以組件也是不會重新渲染的。這個時候我們就需要進(jìn)行深拷貝,創(chuàng)建一個新的對象或數(shù)組,將原對象的各項屬性的"值"(數(shù)組的所有元素)拷貝過來,是"值"而不僅僅是"引用地址"。我們可以使用slice()方法:
ew_state.todos = new_state.todos.slice();
或者引入immutable庫來實現(xiàn)數(shù)據(jù)不可變。
原生渲染native
native指的是使用原生API來開發(fā)App,比如ios使用OC語言,android使用java。
vue
vue和Weex進(jìn)行官方合作,weex是阿里巴巴發(fā)起的跨平臺用戶界面開發(fā)框架,它的思想是多個平臺,只寫一套代碼,weex允許你使用 vue 語法開發(fā)不僅僅可以運行在瀏覽器端,還能被用于開發(fā) iOS 和 Android 上的原生應(yīng)用的組件。即只需要編寫一份代碼,即可運行在Web、iOS、Android上。
weex相對來說上手比較簡單,安裝vue-cli之后就可以使用,學(xué)習(xí)門檻低,但是它的社區(qū)目前還處于成長期,react native的社區(qū)非常成熟活躍,有非常豐富的組件可供擴(kuò)展。
react
react native是Facebook在2015年3月在F8開發(fā)者大會上開源的跨平臺UI框架,需針對iOS、Android不同編寫2份代碼,使用react native需要按照文檔安裝配置很多依賴的工具,相對比較麻煩。weex的思想是多個平臺,只寫一套代碼,而react-native的思想是多個平臺可以寫多套代碼,但其使用的是同一套語言框架。
weex的目標(biāo)在于抹平各個平臺的差異性,從而簡化應(yīng)用開發(fā)。而react-native承認(rèn)了各個平臺之間的差異,退而求其次,在語言和框架層面對平臺進(jìn)行抽象,從方法論的角度去解決多平臺開發(fā)的問題。
ssr服務(wù)端渲染
服務(wù)端渲染核心在于方便seo優(yōu)化,后端先調(diào)用數(shù)據(jù)庫,獲得數(shù)據(jù)之后,將數(shù)據(jù)和頁面元素進(jìn)行拼裝,組合成完整的html頁面,再直接返回給瀏覽器,以便用戶瀏覽。
vue
2016 年 10 月 25 日,zeit.co背后的團(tuán)隊對外發(fā)布了 Next.js,一個 React 的服務(wù)端渲染應(yīng)用框架。幾小時后,與 Next.js 異曲同工,一個基于 Vue.js 的服務(wù)端渲染應(yīng)用框架應(yīng)運而生,我們稱之為:Nuxt.js。
服務(wù)端渲染支持流式渲染,因為HTTP請求也是流式,Vue 的服務(wù)端渲染結(jié)果可以直接 pipe 到返回的請求里面。這樣一來,就可以更早地在瀏覽器中呈現(xiàn)給用戶內(nèi)容,通過合理的緩存策略,可以有效地提升服務(wù)端渲染的性能。
- 基于 Vue.js
- 自動代碼分層
- 服務(wù)端渲染
- 強(qiáng)大的路由功能,支持異步數(shù)據(jù)
- 靜態(tài)文件服務(wù)
- ES2015+ 語法支持
- 打包和壓縮 JS 和 CSS
- HTML 頭部標(biāo)簽管理
- 本地開發(fā)支持熱加載
- 集成 ESLint
- 支持各種樣式預(yù)處理器: SASS、LESS、 Stylus 等等
- 支持 HTTP/2 推送
react
Next是一個React框架,允許使用React構(gòu)建SSR和靜態(tài)web應(yīng)用
服務(wù)器渲染,獲取數(shù)據(jù)非常簡單
無需學(xué)習(xí)新框架,支持靜態(tài)導(dǎo)出。
支持CSS-in-JS庫
自動代碼拆分,加快頁面加載速度,不加載不必要的代碼
基于Webpack的開發(fā)環(huán)境,支持模塊熱更新(HMR)
支持Babel和Webpack自定義配置服務(wù)器、路由和next插件。
能夠部署在任何能運行node的平臺
內(nèi)置頁面搜索引擎優(yōu)化(SEO)處理
在生產(chǎn)環(huán)境下,打包文件體積更小,運行速度更快
生命周期
vue
【初始化階段(4個)】
(1)beforeCreate
此鉤子函數(shù)不能獲取到數(shù)據(jù),dom元素也沒有渲染出來,此鉤子函數(shù)不會用來做什么事情。
(2)created
此鉤子函數(shù),數(shù)據(jù)已經(jīng)掛載了,但是dom節(jié)點還是沒有渲染出來,在這個鉤子函數(shù)里面,如果同步更改數(shù)據(jù)的話,不會影響運行中鉤子函數(shù)的執(zhí)行。可以用來發(fā)送ajax請求,也可以做一些初始化事件的相關(guān)操作。
(3)beforeMount
代表dom節(jié)點馬上要被渲染出來了,但是還沒有真正的渲染出來,此鉤子函數(shù)跟created鉤子函數(shù)基本一樣,也可以做一些初始化數(shù)據(jù)的配置。
(4)mounted
是生命周期初始化階段的最后一個鉤子函數(shù),數(shù)據(jù)已經(jīng)掛載完畢了,真實dom也可以獲取到了。
【運行中階段(2個)】
(5)beforeUpdate
運行中鉤子函數(shù)beforeUpdate默認(rèn)是不會執(zhí)行的,當(dāng)數(shù)據(jù)更改的時候,才會執(zhí)行。數(shù)據(jù)更新的時候,先調(diào)用beforeUpdate,然后數(shù)據(jù)更新引發(fā)視圖渲染完成之后,再會執(zhí)行updated。運行時beforeUpdate這個鉤子函數(shù)獲取的數(shù)據(jù)還是更新之前的數(shù)據(jù)(獲取的是更新前的dom內(nèi)容),在這個鉤子函數(shù)里面,千萬不能對數(shù)據(jù)進(jìn)行更改,會造成死循環(huán)。
(6)updated
這個鉤子函數(shù)獲取的數(shù)據(jù)是更新后的數(shù)據(jù),生成新的虛擬dom,跟上一次的虛擬dom結(jié)構(gòu)進(jìn)行比較,比較出來差異(diff算法)后再渲染真實dom,當(dāng)數(shù)據(jù)引發(fā)dom重新渲染的時候,在updated鉤子函數(shù)里面就可以獲取最新的真實dom了。
【銷毀階段(2個)】
(7)beforeDestroy
切換路由的時候,組件就會被銷毀了,銷毀之前執(zhí)行beforeDestroy。在這個鉤子函數(shù)里面,我們可以做一些善后的操作,例如可以清空一下全局的定時器(created鉤子函數(shù)綁定的初始化階段的事件)、清除事件綁定。
(8)destoryed
組件銷毀后執(zhí)行destroyed,銷毀后組件的雙向數(shù)據(jù)綁定、事件監(jiān)聽watcher相關(guān)的都被移除掉了,但是組件的真實dom結(jié)構(gòu)還是存在在頁面中的。
添加keep-alive標(biāo)簽后會增加active和deactive這兩個生命周期函數(shù),初始化操作放在actived里面,一旦切換組件,因為組件沒有被銷毀,所以它不會執(zhí)行銷毀階段的鉤子函數(shù),所以移除操作需要放在deactived里面,在里面進(jìn)行一些善后操作,這個時候created鉤子函數(shù)只會執(zhí)行一次,銷毀的鉤子函數(shù)一直沒有執(zhí)行。

react
【初始化階段(5個)】:
(1)getDefaultProps:實例化組件之后,組件的getDefaultProps鉤子函數(shù)會執(zhí)行
這個鉤子函數(shù)的目的是為組件的實例掛載默認(rèn)的屬性
這個鉤子函數(shù)只會執(zhí)行一次,也就是說,只在第一次實例化的時候執(zhí)行,創(chuàng)建出所有實例共享的默認(rèn)屬性,后面再實例化的時候,不會執(zhí)行g(shù)etDefaultProps,直接使用已有的共享的默認(rèn)屬性
理論上來說,寫成函數(shù)返回對象的方式,是為了防止實例共享,但是react專門為了讓實例共享,只能讓這個函數(shù)只執(zhí)行一次
組件間共享默認(rèn)屬性會減少內(nèi)存空間的浪費,而且也不需要擔(dān)心某一個實例更改屬性后其他的實例也會更改的問題,因為組件不能自己更改屬性,而且默認(rèn)屬性的優(yōu)先級低。
(2)getInitialState:為實例掛載初始狀態(tài),且每次實例化都會執(zhí)行,也就是說,每一個組件實例都擁有自己獨立的狀態(tài)。
(3)componentWillMount:執(zhí)行componentWillMount,相當(dāng)于Vue里的created+beforeMount,這里是在渲染之前最后一次更改數(shù)據(jù)的機(jī)會,在這里更改的話是不會觸發(fā)render的重新執(zhí)行。
(4)render:渲染dom
render()方法必須是一個純函數(shù),他不應(yīng)該改變state,也不能直接和瀏覽器進(jìn)行交互,應(yīng)該將事件放在其他生命周期函數(shù)中。 如果shouldComponentUpdate()返回false,render()不會被調(diào)用。
(5)componentDidMount:相當(dāng)于Vue里的mounted,多用于操作真實dom
【運行中階段(5個)】
當(dāng)組件mount到頁面中之后,就進(jìn)入了運行中階段,在這里有5個鉤子函數(shù),但是這5個函數(shù)只有在數(shù)據(jù)(屬性、狀態(tài))發(fā)送改變的時候才會執(zhí)行
(1)componentWillReceiveProps(nextProps,nextState)
當(dāng)父組件給子組件傳入的屬性改變的時候,子組件的這個函數(shù)才會執(zhí)行。初始化props時候不會主動執(zhí)行
當(dāng)執(zhí)行的時候,函數(shù)接收的參數(shù)是子組件接收到的新參數(shù),這個時候,新參數(shù)還沒有同步到this.props上,多用于判斷新屬性和原有屬性的變化后更改組件的狀態(tài)。
(2)接下來就會執(zhí)行shouldComponentUpdate(nextProps,nextState),這個函數(shù)的作用:當(dāng)屬性或狀態(tài)發(fā)生改變后控制組件是否要更新,提高性能,返回true就更新,否則不更新,默認(rèn)返回true。
接收nextProp、nextState,根據(jù)根據(jù)新屬性狀態(tài)和原屬性狀態(tài)作出對比、判斷后控制是否更新
如果shouldComponentUpdate()返回false,componentWillUpdate,render和componentDidUpdate不會被調(diào)用。
(3)componentWillUpdate,在這里,組件馬上就要重新render了,多做一些準(zhǔn)備工作,千萬千萬,不要在這里修改狀態(tài),否則會死循環(huán) 相當(dāng)于Vue中的beforeUpdate
(4)render,重新渲染dom
(5)componentDidUpdate,在這里,新的dom結(jié)構(gòu)已經(jīng)誕生了,相當(dāng)于Vue里的updated
【銷毀階段】
當(dāng)組件被銷毀之前的一剎那,會觸發(fā)componentWillUnmount,臨死前的掙扎
相當(dāng)于Vue里的beforeDestroy,所以說一般會做一些善后的事情,例如使定時器無效,取消網(wǎng)絡(luò)請求或清理在componentDidMount中創(chuàng)建的任何監(jiān)聽。

銷毀組件
vue
vue在調(diào)用$destroy方法的時候就會執(zhí)行beforeDestroy生命周期函數(shù),然后組件被銷毀,這個時候組件的dom結(jié)構(gòu)還存在于頁面結(jié)構(gòu)中,也就說如果想要對殘留的dom結(jié)構(gòu)進(jìn)行處理必須在destroyed生命周期函數(shù)中處理。
react
react執(zhí)行完componentWillUnmount之后把事件、數(shù)據(jù)、dom都全部處理掉了,也就是說當(dāng)父組件從渲染這個子組件變成不渲染這個子組件的時候,子組件相當(dāng)于被銷毀,所以根本不需要其他的鉤子函數(shù)了。react銷毀組件的時候,會將組件的dom結(jié)構(gòu)也移除,vue則不然,在調(diào)用destory方法銷毀組件的時候,組件的dom結(jié)構(gòu)還是存在于頁面中的,this.$destory組件結(jié)構(gòu)還是存在的,只是移除了事件監(jiān)聽,所以這就是為什么vue中有destroyed,而react卻沒有componentDidUnmount。
狀態(tài)集管理工具
vue
vuex是一個專門為vue構(gòu)建的狀態(tài)集管理工具,vue和react都是基于組件化開發(fā)的,項目中包含很多的組件,組件都會有組件嵌套,想讓組件中的數(shù)據(jù)被其他組件也可以訪問到就需要使用到Vuex。
[圖片上傳失敗...(image-2a0a7e-1565257938346)]
vuex的流程
- 將需要共享的狀態(tài)掛載到state上:this.$store.state來調(diào)用
創(chuàng)建store,將狀態(tài)掛載到state上,在根實例里面配置store,之后我們在組件中就可以通過this.$store.state來使用state中管理的數(shù)據(jù),但是這樣使用時,當(dāng)state的數(shù)據(jù)更改的時候,vue組件并不會重新渲染,所以我們要通過計算屬性computed來使用,但是當(dāng)我們使用多個數(shù)據(jù)的時候這種寫法比較麻煩,vuex提供了mapState輔助函數(shù),幫助我們在組件中獲取并使用vuex的store中保存的狀態(tài)。
- 我們通過getters來創(chuàng)建狀態(tài):通過this.$store.getters來調(diào)用
可以根據(jù)某一個狀態(tài)派生出一個新狀態(tài),vuex也提供了mapGetters輔助函數(shù)來幫助我們在組件中使用getters里的狀態(tài)。
- 使用mutations來更改state:通過this.$store.commit來調(diào)用
我們不能直接在組件中更改state,而是需要使用mutations來更改,mutations也是一個純對象,里面包含很多更改state的方法,這些方法的形參接收到state,在函數(shù)體里更改,這時,組件用到的數(shù)據(jù)也會更改,實現(xiàn)響應(yīng)式。vuex提供了mapMutations方法來幫助我們在組件中調(diào)用mutations 的方法。
- 使用actions來處理異步操作:this.$store.dispatch來調(diào)用
Actions類似于mutations,不同在于:Actions提交的是mutations,而不是直接變更狀態(tài)。Actions可以包含任意異步操作。也就是說,如果有這樣的需求:在一個異步操作處理之后,更改狀態(tài),我們在組件中應(yīng)該先調(diào)用actions,來進(jìn)行異步動作,然后由actions調(diào)用mutations來更改數(shù)據(jù)。在組件中通過this.$store.dispatch方法調(diào)用actions的方法,當(dāng)然也可以使用mapMutations來輔助使用。
react
2015年Redux出現(xiàn),將 Flux 與函數(shù)式編程結(jié)合一起,很短時間內(nèi)就成為了最熱門的前端架構(gòu)。它的出現(xiàn)主要是為解決react中組件之間的通信問題。建議把數(shù)據(jù)放入到redux中管理,目的就是方便數(shù)據(jù)統(tǒng)一,好管理。項目一旦出現(xiàn)問題,可以直接定位問題點。組件擴(kuò)展的時候,后續(xù)涉及到傳遞的問題。本來的話,組件使用自己的數(shù)據(jù),但是后來公用組件,還需要考慮如何值傳遞,在redux中可以存儲至少5G以上的數(shù)據(jù)。
redux的流程

-
創(chuàng)建store:
從redux工具中取出createStore去生成一個store。
-
創(chuàng)建一個reducer,然后將其傳入到createStore中輔助store的創(chuàng)建。
reducer是一個純函數(shù),接收當(dāng)前狀態(tài)和action,返回一個狀態(tài),返回什么,store的狀態(tài)就是什么,需要注意的是,不能直接操作當(dāng)前狀態(tài),而是需要返回一個新的狀態(tài)。
想要給store創(chuàng)建默認(rèn)狀態(tài)其實就是給reducer一個參數(shù)創(chuàng)建默認(rèn)值。
組件通過調(diào)用store.getState方法來使用store中的state,掛載在了自己的狀態(tài)上。
組件產(chǎn)生用戶操作,調(diào)用actionCreator的方法創(chuàng)建一個action,利用store.dispatch方法傳遞給reducer
reducer對action上的標(biāo)示性信息做出判斷后對新狀態(tài)進(jìn)行處理,然后返回新狀態(tài),這個時候store的數(shù)據(jù)就會發(fā)生改變, reducer返回什么狀態(tài),store.getState就可以獲取什么狀態(tài)。
我們可以在組件中,利用store.subscribe方法去訂閱數(shù)據(jù)的變化,也就是可以傳入一個函數(shù),當(dāng)數(shù)據(jù)變化的時候,傳入的函數(shù)會執(zhí)行,在這個函數(shù)中讓組件去獲取最新的狀態(tài)。
小結(jié)
vue和react的核心都是專注于輕量級的視圖層,雖然只是解決一個很小的問題,但是它們龐大的生態(tài)圈提供了豐富的配套工具,一開始它并不會給你提供全套的配置方案,將所有的功能都一次性給你打包好,它只會給你提供一些簡單的核心功能,當(dāng)你需要做一個更復(fù)雜的應(yīng)用時,再增添相應(yīng)的工具。例如做一個單頁應(yīng)用的時候才需要用路由;做一個相當(dāng)龐大的應(yīng)用,涉及到多組件狀態(tài)共享以及多個開發(fā)者共同協(xié)作時,才可能需要大規(guī)模狀態(tài)管理方案。
框架的存在就是為了幫助我們應(yīng)對不同的項目復(fù)雜度,當(dāng)我們面對一個大型、復(fù)雜的開發(fā)項目時,使用太簡陋的工具會極大的降低開發(fā)人員的生產(chǎn)力,影響工作效率,框架的誕生就是在這些工程中提取一些重復(fù)的并且已經(jīng)受過驗證的模式,抽象到一個已經(jīng)幫你設(shè)計好的API封裝當(dāng)中,幫助我們?nèi)?yīng)對不同復(fù)雜度的問題。所以在開發(fā)的過程中,選擇一個合適的框架就會事半功倍。但是,框架本身也有復(fù)雜度,有些框架會讓人一時不知如何上手。當(dāng)你接到一個并不復(fù)雜的需求,卻使用了很復(fù)雜的框架,那么就相當(dāng)于殺雞用牛刀,會遇到工具復(fù)雜度所帶來的副作用,不僅會失去工具本身所帶來優(yōu)勢,還會增加各種問題,例如學(xué)習(xí)成本、上手成本,以及實際開發(fā)效率等。
所以并不是說做得少的框架就不如做的做的框架,每個框架都有各自的優(yōu)勢和劣勢,并不能找到完全符合需求的框架,最重要的適合當(dāng)前項目,目前兩大框架的生態(tài)圈一片繁榮,react社區(qū)是當(dāng)前最活躍的,最快的時候三天更新一個版本,一個問題可能存在幾十種不同的解決方案,這就需要我們前端人員去在不同的功能之間做取舍,以后前端框架的發(fā)展方向應(yīng)該是小而精、靈活以及開放的,核心功能+生態(tài)附加庫可以幫我們更加靈活的構(gòu)建項目,為了跟上前進(jìn)的腳步,就需要不停的吸收最新的內(nèi)容,這也是從事前端開發(fā)領(lǐng)域的一大樂趣,希望大家都能在學(xué)習(xí)中獲得長足的進(jìn)步。

參考文章及站點:
React官網(wǎng)
Vue官網(wǎng)
Vue官網(wǎng):對比其他框架
https://vue.docschina.org/v2/guide/comparison.html
Nuxt.js
vue和react對比(詳解)
https://www.cnblogs.com/yangyangxxb/p/10105856.html
react和vue對比
http://www.itdecent.cn/p/3fbbb0bce78a
vue和react的區(qū)別之我見
http://www.itdecent.cn/p/b7cd52868e95?from=groupmessage
如何選擇正確的后端渲染框架:Next, Nuxt, Nest?
http://www.itdecent.cn/p/00d46b269b8e
react服務(wù)端渲染
http://www.itdecent.cn/p/5cbc3349819f
Vue.js 服務(wù)器端渲染指南
React Native--概述及與Weex和Native開發(fā)的對比(一)
http://www.itdecent.cn/p/613c1e8611e9
Weex 和 React Native的比較
http://www.itdecent.cn/p/3231d5d20f7b
Weex 和 React Native 的比較看這里
https://www.cnblogs.com/Free-Thinker/p/8491724.html
【前端前沿看點】深度本質(zhì)分析對比weex和react native
https://blog.csdn.net/chaunceyw/article/details/78151222
Vue2.0 中,“漸進(jìn)式框架”和“自底向上增量開發(fā)的設(shè)計”這兩個概念是什么?
https://www.zhihu.com/question/51907207
Vue作者尤雨溪:Vue 2.0,漸進(jìn)式前端解決方案
vue內(nèi)置指令與自定義指令
https://www.cnblogs.com/ilovexiaoming/p/6840383.html
React的setState和數(shù)據(jù)綁定
https://blog.csdn.net/weixin_33805992/article/details/88179779
React實現(xiàn)數(shù)據(jù)雙向綁定
https://blog.csdn.net/Chad97/article/details/88092284
【譯】react:css in js