由於Vuex和Redux都是從Flux中衍生出來,同時Vuex對Redux部分思想也有一些借鑑,所以Vuex和Redux有很多相同點。很多資料也有介紹兩者的對比,但大部分講解的比較抽象,較難理解。筆者整理兩者異同點,同時配有標準案例進行說明。注意本文不是科普vuex和redux相關概念,相關知識內容可以在官方文件中檢視。Vuex (opens new window)、Redux(opens new window)
-
異同點
-
相同點
- state 共享資料
- 流程一致:定義全域性state,觸發,修改state
- 原理相似,透過全域性注入store。
-
不同點
- 從實現原理上來說:
- Redux 使用的是不可變資料,而Vuex的資料是可變的。Redux每次都是用新的state替換舊的state,而Vuex是直接修改
- Redux 在檢測資料變化的時候,是透過 diff 的方式比較差異的,而Vuex其實和Vue的原理一樣,是透過 getter/setter來比較的
- 從表現層來說:
vuex
定義了state、getter、mutation、action
四個物件;redux
定義了state、reducer、action
。vuex
中state
統一存放,方便理解;redux
state依賴所有reducer的初始值vuex
有getter
,目的是快捷得到state;redux
沒有這層,react-redux mapStateToProps引數做了這個工作。vuex
中mutation
只是單純賦值(很淺的一層);redux
中reducer
只是單純設定新state(很淺的一層)。他倆作用類似,但書寫方式不同vuex
中action
有較為複雜的非同步ajax請求;redux
中action中可簡單可複雜,簡單就直接傳送資料物件({type:xxx, your-data}),複雜需要呼叫非同步ajax(依賴redux-thunk外掛)。
vuex觸發方式
有兩種commit同步和dispatch非同步;redux
同步和非同步都使用dispatch
- 從實現原理上來說:
詳細解釋
-
Vuex
- 型別
- state: 共享資料
- getter: 快捷state
- mutation: 同步更新,只是簡單都賦值
- action: 非同步更新,可以呼叫commit來觸發同步mutation
- 觸發
- commit 觸發mutation同步操作
- dispatch 觸發action非同步操作
- 庫結合(自帶)
- mapState
- mapGetters
- mapMutations
- mapActions
- 其他
- UI跟state、action/dispatch相關
- mutations 同步修改state。UI觸發使用commit指令
- action 內可以commit同步state或dispatch非同步另外一個action。UI觸發使用dispatch指令
- 型別
-
Redux
- 型別
- store: 合併所有reducer,共享資料
- reducer: 兩個作用:1. 初始值合併獲得state 2. 簡單的賦值,獲取新的state代替老的state
- action: 觸發函式。是
唯一
可以帶上資料修改state的觸發物件。接下邏輯就轉移到reducer中
注:也可以反過來理解:Vuex的每一次this.$store.commit('type', data) === action(data){ return { type, data}})
- 觸發 (依賴react-redux)
- dispatch觸發同步或非同步。使用mapDispatchToProps引數
- 庫結合(依賴react-redux)
- mapStateToProps
- mapDispatchToProps
- 型別
簡單理解,reducer承擔了state和mutations功能。 Vuex中commit-mutations是唯一修改state的方式;Redux中dispatch-reducer是唯一修改state方式
Vuex典型案例
// vuex非常簡單易懂,而且整理到1個檔案即可 const state: IState = { login: false, option: { _id: '', sub_title: '', title: '', keyword: '', descript: '', url: '', email: '', icp: '' } } const actions: ActionTree<IState, any> = { // 登入 async login ({ commit }, user: StoreState.Login): Promise<Ajax.AjaxResponse> { commit('USER_LOGINING') const res: Ajax.AjaxResponse = await service.login({ ...user }) commit('USER_LOGINING_FINAL') return res }, } const mutations: MutationTree<IState> = { 'USER_LOGINING' (state: IState): void { state.login = true }, 'USER_LOGINING_FINAL' (state: IState): void { state.login = false }, } export default new Vuex.Store({ state, actions, mutations, modules })
Redux典型案例
// store.js import { createStore, combineReducers, applyMiddleware } from 'redux' import home from './home/reducer' import demo from './demo/reducer' import thunk from 'redux-thunk' // reducers獲得初始state let store = createStore(combineReducers({ home, demo }), applyMiddleware(thunk)) export default store
// reducer.js let defaultState = { demoList: [] } export default (state = defaultState, action) => { switch (action.type) { case 'setDemoList': return { ...state, demoList: action.list } default: return state } }
// action.js // 同步action export const setDemoList = list => ({ type: 'setDemoList', list }) // 非同步action export const setAsyncList = () => { return async dispatch => { let result = await API.getXXX() dispatch({type: 'setAsyncList', result}) } }
// ui const mapStateToProps = (state) => { return { list: state.demo.demoList } } // const mapDispatchToProps = (dispatch) => { // return { // setDemoList: list => dispatch(setDemoList(list)) // } // } // or const mapDispatchToProps = {setDemoList} export default connect(mapStateToProps, mapDispatchToProps)(Demo)
總結
- vuex的流向:
- view——>commit——>mutations——>state變化——>view變化(同步操作)
- view——>dispatch——>actions——>mutations——>state變化——>view變化(非同步操作)
- redux的流向:view——>actions——>reducer——>state變化——>view變化(同步非同步一樣)
參考文章
- Redux vs. Vuex(opens new window)
- How Vuex compares to redux for Managing State Object(opens new window)
- Redux & 與vuex的對比
-