vue和react的差別

引言

平時開發單頁項目應用基於vue,目前另外兩個比較熱的庫還有angular和react,angular 1系列用過,進入公司後因爲基於vue技術棧就沒在關注了。
一直在關注react,目的不是學習用法,只是爲了拓展本身的視野和思惟,經過了解一些使用上的差別性,來進一步的思考其底層設計的思想。css

環境搭建

在具體業務邏輯開發前,咱們首先要作的是搭建項目骨架,vue的話可使用vue-cli,經過腳手架產生的配置徹底暴露出來,咱們能夠靈活的修改配置來定製化需求。
我經常使用幾個配置以下html

build時assetsPublicPath會修改爲相對引入,或者配置成公共前綴,方便測試
    dev時proxyTable代理一些接口,聯調用,本身測試話就直接用mock數據服務
    關閉devtool,去除contenthash,chunkhash,html的minify,添加externals,定製化一些eslint……等等
    其它也有一些不通用改動,上面是每一個項目都通用的配置

至於react可使用create-react-app架手架,而後就直接可使用create-react-app建立項目了,默認隱藏配置,定製化配置能夠直接npm run eject。須要注意點就是使用create-react-app建立比較慢,須要作以下設置vue

npm config set registry https://registry.npm.taobao.org

其實自定義配置直接在配置依賴包裏也能夠改動,不過這樣不太好。其次腳手架建立項目最好不要在已有git目錄下載建立,否則使用npm run eject會報錯,此時用空目錄下建立便可。
不管是哪一個腳手架經常使用的配置,都是基於webpack核心生態圈構建,因此核心重點就是webpack用的熟練的話,不管使用哪一個自定義化配置都不成問題。react

使用

vue稍微複雜些單頁會基於vue+vuex+vue-router,react棧是react+redux+react-router。
不一樣點是vue組件是(html+css+js),對開發友好,上手容易。react一切都是js,特別的靈活,經過在render中利用純js邏輯控制渲染輸出模板。下面是基於react的一個示例。webpack

render() {
    let name = this.state.flag ? 'true':'false'
    return (
        <ul>
            {this.props.items.map(item => (
                <li key={item.id}>{item.text}</li>
            ))}
            {name}
        </ul>
    );
}

vue的語法糖可讓咱們在表單上輕鬆的實現雙向綁定,而react是純粹的基於UI=render(data)的理念。vue利用es5的set,get機制收集依賴,能詳細的定位修改元素,react每次setState對組件構造函數中私有屬性進行修改時,組件都會更新,除非你在shouldComponentUpdate加入一些邏輯處理。另外vue提供的api多,有不少好用又方便的指令,可是具備兩面性,而react核心概念少,js用的溜,上手挺容易的。git

數據流

不管是vue仍是react都支持組件私有屬性;組件之間prop,組件之間簡單關數據系修改的話,可使用事件的方式,vue此時又提供了個語法糖sync,吼吼,其它的話沒啥差別。web

比較麻煩的一點就是複雜網狀組件之間數據流動時處理,此時就須要合理組織數據了,否則維護,調試就是一個大坑,事件方式就不適合了,此時就要說到vuex和redux了,vuex的getter獲取state中數據,映射到組件data屬性上,Mutation同步commit修改數據,Action中dispatch可同步or異步修改數據,核心是單一狀態樹,經過設計層層方法最後達到修改數據的目的就是爲了更好的管理,檢測數據的流動。redux由於平時用的少,因此此刻我要描述的詳細些,以作備忘。算法

import {createStore, applyMiddleware, compose} from 'redux'
import thunk from 'redux-thunk'
import {Provider} from 'react-redux'
const store = createStore(counter,
    compose(
        applyMiddleware(thunk),
        window.devToolsExtension?window.devToolsExtension(): f => f
    )) 
ReactDOM.render(
    <Provider store={store}>
        <JSDT/>
    </Provider>,
    document.getElementById('root')
);

瞭解背後原理,可讓咱們更靈活的控制代碼,下面開始詳細的分析。
執行createStore,提供一個狀態樹的初始化環境,返回一個對象,其中包含一些閉包函數,引用createStore初始化環境中中的各類函數和變量,例如dispatch(派發action),getState(獲取只讀狀態樹上的值),subscribe(訂閱數據改變)等等,其中spring

dispatch({ type: ActionTypes.INIT })(源碼:248)

此代碼的目的是建立store的時候,給reduce一個默認值,初始化currentState值,方便初次getState調用。vue-router

applyMiddleware中間件機制,能夠在處理store先後加一些通用處理,其它例如express,koa,springMVC這些框架中都有這種思想,實現方式不一樣,目的都同樣,解耦,可插拔效果,便於維護。
而rudux中applyMiddleware實現原理是利用高階函數compose,經過reduce將多個函數組合成一個可執行執行函數,關鍵步驟代碼以下所示。

//applyMiddleware.js
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
//compose.js
funcs.reduce((a, b) => (...args) => a(b(...args)))

thunk 至於這個就是用來方便作異步處理的,是一個高階函數中間件,以下所示,通常action返回的都是一個行爲描述對象,可是這個在你對store進行處理前加了一層邏輯判斷,以便咱們在組件上統一的方式寫dispatch相關的代碼。

if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

devToolsExtension //開啓調試工具,沒有vue方便,不能自動檢測

Provider提供一個上下文環境,讓一個樹上的全部組件都能訪問同一個對象。必要前提條件是添加加childContextTypes和getChildContext。

優化

爲了更好的體驗,通常咱們會採起一些措施,下面總結一下針對vue和react的優化措施。
重單頁應用,在路由中咱們能夠異步加載組件,雖然二者都支持,原理相似,可是vue使用極其方便,以下所示

const My = () => import('../components/My.vue')

有一點須要注意的就是須要配置下assetsPublicPath,這樣打包後的url中是全路徑,不然按照相對路徑處理容易出問題;相對而言react還要用模板代碼包裝下組件,這一點很差,不過將來react將來會開啓異步渲染組件的支持,這一點很贊。

vue和react都是基於dom diff更新差別元素。vue中,咱們操做的data數據是vue封裝處理過,修改數據時,vue會將數據初始化時收集的相關依賴元素進行更新,而react每次setState更新數據針對的是組件,爲了優化,組件設計的時候儘可能細粒度,尤爲是react當中的展現類組件。

由於二者使用的是針對web頁面狀況優化過的dom diff算法,以使複雜度下降爲O(n),因此有一些默認前提,理解並按照默認diff規則才能使代碼達到最優,好比說,保持根節點一致;一個dom父節點下有多個子節點並列時,給子節點添加key,防止對父節點使用insertBefore插入子節點這種狀況等等。

總結

陸陸續續的學習過程當中,將本身的想法本身總結下來。

說明,文中的總結基於下面這些版本,vue ^2.4.2react 16.0.0-rc.2redux 3.7.2react-router 4.2

相關文章
相關標籤/搜索