當前位置:
首頁 > 知識 > Vue 用戶的 React 上手小結

Vue 用戶的 React 上手小結

Vue 用戶的 React 上手小結



這是一份從Vue用戶角度出發的React上手總結與對比。


構建系統


正常的前端工程化項目中,二者均採用Webpack/NPM作為模塊打包和依賴管理工具。

雖然不同腳手架所定製的Webpack配置有所區別,但實際上切換腳手架的難度可以說是最低的。


以至於


vue-springbud


(https://github.com/doodlewind/vue-springbud)


這個Vue腳手架可以構建配置一行不改,直接用於打包React項目(當然了,會缺失HMR與樣式預編譯等高級功能)。


React的生態更大而鬆散,體現在構建配置上,就是官方的loader更加專註JSX編譯,而不像vue-loader這樣既編譯模板,又預編譯樣式。


React的腳手架配置需要更多地定製樣式方面的配置,如css-loader/預處理器/CSS Module配置等。


不過在JS轉譯/Uglify/CommonChunk提取/ 全局變數/各類Assets loaders/開發環境Proxy等通用的Webpack功能使用上,二者的配置方式基本是一致的。


基礎 API 與功能實現


渲染數據

和Vue在HTML template內寫{}的形式不同,React將各種數據嵌套在JSX表達式中,然後render JSX到頁面上。


在渲染數組時,React中經常利用map將數據片段映射成一段JSX,然後在列表區域中直接引用map後的JSX變數來渲染數組數據。


而Vue中則使用類似Smarty語法的v-for指令來渲染數組。


同時,React需要為數據添加key來保證虛擬 DOM diff演算法的效率,而Vue中除非渲染的列表也是組件,否則一般不需提供類似用於優化的欄位。


渲染數據時另一種常見的需求是,將後端提供的數據進行一些簡單的轉換後再渲染至頁面上。在Vue中提供了組件的computed屬性來實現這一功能,而React中則需要在render函數中定義一個新變數,將轉換後的值賦給這個變數後render它。


更新數據


Vue和React組件內的this指向的都是組件的實例,它們都可以通過修改實例數據來更新頁面。區別在於,Vue中的this沒有提供state/props/setState API,不論是父組件傳入的數據還是子組件的數據,都在同一個this的作用域下(這樣業務代碼會更短一些)。


並且,Vue也沒有setState這樣的setter方法來更新數據,直接通過全量賦值this.xxx=yyy數據的方式就可以更新 DOM 了。


React和Vue的設計區別,在更新數據的API中可以得到體現。Vue的依賴追蹤Hack了對象的setter,因此在執行簡單的賦值操作時可以直接獲知狀態樹中的修改位置,但DOM更新是非同步的。因此在Vue中如下的代碼是沒有問題的:


需要顯式setState的React則不能從基礎的賦值操作中獲知變更內容,而是需要通過setState觸發一次render,而後在render中更新DOM狀態。因此這是一個容易踩的坑:

React中DOM狀態和數據狀態都是非同步更新的。Vue中僅DOM狀態非同步更新,需要保證DOM狀態正確更新時,所使用的Vue.nextTick()API實際上也類似於React的setState回調。


用戶輸入


與Vue中通過v-model綁定input等輸入元素的方式不同,React中在JSX里使用Input標籤時,需要顯式為表單的JSX提供一個onChange屬性,在此屬性中指定一個名稱形如handleInput的函數,在函數中調用React的this.setState()來更改狀態。


這個handler函數如果不在React組件實例中聲明,那麼則需要通過在constructor中添加this.handleXXX=handleXXX.bind(this)的方式來綁定函數中的this到React組件實例。


當存在多個input標籤時,React可以復用同一個handler函數,並在其中通過類似setState({ [name]: data })的語法糖來減少冗餘代碼(當然了這樣也比v-model要繁瑣一些)。


減少這些冗餘代碼的一種方式,是將基礎的輸入標籤(或標籤組)封裝為React的組件,並通過父子組件通信的方式來處理表單中用戶輸入狀態的更新。


事件傳遞


事件傳遞在Vue中是通過v-on和$emit來實現的。在父組件模板中聲明子組件時,通過v-on:childEventName="parentHandler"語法來指定對子組件特定名稱事件的Handler method。而遷移到React中後,其事件傳遞的機制有所區別。


另外,在React中常見組件ref屬性,可以使用這一屬性來在父組件中安全地調用子組件方法。而在Vue中雖然可以通過$ref獲取到子組件狀態,但這並不是一個推薦的做法。


狀態管理

React本身是一個純View庫,沒有狀態管理功能。因此在大型應用中需要Redux這樣的庫來做狀態管理。相應的概念在Vue中則是Vuex。二者所引入的新概念學習成本是相近的,從一種遷移到另一種也並不困難。


Vuex中,需要理解的核心概念是mutation和action。這兩種概念是從同步和非同步的角度出發去實現的。可以簡單理解為【同步狀態改變就commit一個mutation,非同步的狀態操作就dispatch一個action】。


在action中可以commit一個或多個mutation,也可以觸發其它Promise/async化的action來實現靈活的非同步控制流組合。


這個思維模式切換到Redux的reducer/action概念中,需要澄清的則是:


mutation和reducer並沒有什麼關係(不過它們確實都是同步的)。


Redux的action既可以同步,也可以非同步。


在最簡單的情景下,Redux中狀態的更改,首先需要dispatch一個action函數。


這個action函數會返回一個帶有type類型的原生JS對象,action觸發後,Redux根據action的類型去執行reducer中的邏輯,根據action返回的type以及相應的數據,決定如何更新全局狀態。


reducer中的邏輯是同步的純函數,並且可以通過combileReducers的API來組合多個子頁面的reducer,最後得到整個頁面的狀態樹處理邏輯。


在需要非同步的情景下,action可以不返回原生JS對象,而是返回thunk/promise一類用於非同步操作的數據類型,通過Redux的applyMiddleware API引入處理這些類型數據的能力。

例如redux-thunk就可以使得redux的action不局限於返回一個原生JS對象,而是返回一個【接收dispatch函數】的thunk函數。


這個函數在非同步操作成功時再去調用傳入的dispatch方法,在此提交一個真正觸發reducer邏輯的action。


Redux提供的subscribe API使得它能夠遷移到其它View庫中作為其狀態管理方案。


不過在React中,有react-redux這一中間層包裝了subscribe以及其它的Redux API,從而可以通過包裝根節點組件到Provider組件內,而後connnet組件到Redux的方式,簡化Redux在React項目中的使用。


由於action非同步情境下Redux沒有提供【官方且唯一】的處理方案,因此催生了redux-thunk/redux-promise/redux-saga/dva這樣種類繁多的輔助Middleware。


在這方面,React系確實有更高的可定製性,不過若需要一一了解它們並做技術選型,學習成本還是比引入Vuex要高的。


生態與工具


前文中已經提到了在狀態管理方面,React和Vue的一些異同。下面對比一些其它相關的周邊生態:


Devtools方面,React提供的Chrome開發插件和Vue的插件都對提升開發效率很有幫助。一些區別在於:


React插件支持將選中的組件映射到console的$r變數,更方便地實現調試。

React插件支持對生產環境的頁面進行調試。這在很多時候是很重要的。


React的插件不支持顯示【僅組件】的視圖,較難直接從 devtool視圖中選中想要調試的組件。


調試Redux時React插件沒有官方解決方案,而Vue的插件集成了Vuex的調試功能。


組件庫方面,目前React有相對更加豐富的組件庫,也有RN這樣的跨端解決方案。在Vue方面靠譜的組件庫除了Element UI外並不是很多。


在CSS預處理器支持方面,vue-loader提供了相對更完善的預處理器支持。


引入Sass/Less/Stylus只需指定.vue組件中style標籤中的lang屬性即可。


React的CSS Modules支持需要引入一些自定義的Webpack配置,相對定製性更強,也對boilerplate有更高的要求。


在第三方庫支持方面,二者都有不少封裝第三方庫的組件庫(當然了還是 React 更多)。


不過它們較Angular更為友好的地方在於,在React和Vue的組件中調用第三方庫都是較為方便的,不需要通過react-xxx或vue-xxx的封裝就能夠快速使用常見第三方庫(如圖表、ajax 等)的功能。


常見反模式

在接觸了中等規模(去除組件庫後,整個項目在約萬行級)的React業務代碼後,可以總結出一些常見的坑:


需要前端【更改一下數據格式】的數據一般都會通過map的形式轉換為JSX。但這些代碼經常直接就是放置在render函數中的局部變數,會降低render的可讀性。


未引入Redux時存在著多層組件間的事件傳遞,較為繁瑣。


React缺少原生的watch機制以訂閱某種數據的變更。


新手編寫的JSX頁面中容易混淆模板與UI邏輯,破壞數據和模板的分離解耦。並且JSX也容易變得冗長而不易維護,典型情況如【在JSX中嵌套三目運算符】。


constructor中可能存在大量的bind。


在組件方法中直接編寫各種ajax業務邏輯。


而相應地,在同等規模的Vue項目中也存在一些常見的坑:


未引入Vuex時存在多層的數據傳遞。


相對更簡單的語法造成新人加入時採用各種ES5語法(如使用ES6的函數而非箭頭函數、不用computed而在method中用古老的for循環拼湊數據並手動重置data屬性等)。

在組件中直接執行各種ajax業務邏輯。


類型檢查相對更松。如Vue在2.3之前HTML模板允許標籤不閉合,造成升級後一些模板編寫不嚴謹的頁面大規模報錯等。


總之,React最重要的組件化和狀態管理理念和Vue是一致的,熟悉Vue的開發者遷移過來並不需要很大的學習成本,更多考慮的還是團隊的已有積累和業務方向。


文章來源:


http://ewind.us/2017/vue-to-react/?utm_source=tuicool&utm_medium=referral


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 優才學院 的精彩文章:

10個JavaScript概念!Node.js程序員必須掌握
ui 設計中的插畫與情感化設計
快速學會SVN的搭建和使用
大白話解釋 Git和GitHub
AI取代人類前孩子的教育需要什麼改變?

TAG:優才學院 |

您可能感興趣

Vue+VueRouter+elememntUI+axios 搭建後台管理系統
Angular、React 當前,Vue.js 優劣幾何?
教你使用Vue.js的DevTools來調試你的vue項目
少女歌劇Revue Starlight-ReLIVE特別舞台
《少女歌劇Revue Starlight》手游曝光
Vue: scoped 樣式與 CSS Module 對比
Vue中的methods、watch、computed的區別
Vue.js 為何能逆襲 Angular 和 React 而主導前端?
「少女歌劇Revue Starlight-ReLIVE」特別舞台報道
GitHub趨勢:Vue.js大有超過TensorFlow之勢!
PicGo—基於 electron-vue 的炫酷圖床工具
「少女歌劇 Revue Starlight」公開同名手游新情報!
簡單理解Vue中的nextTick
《少女歌劇Revue Starlight》預約正式開啟
前端圈小可愛Vue的自白:我年少成名卻又屢陷React、Angular混戰
dotnet core webapi+vue 搭建前後端完全分離web架構(一)
手把手教Vue-路由「Vue-rouer」
Angular和Vue.js 深度對比
React和Vue到底誰更牛?
「少女歌劇 Revue Starlight」動畫完結,計劃發售紀念書籍