Vuex與Redux比較

天然呆☆☆發表於2024-11-15

由於Vuex和Redux都是從Flux中衍生出來,同時Vuex對Redux部分思想也有一些借鑑,所以Vuex和Redux有很多相同點。很多資料也有介紹兩者的對比,但大部分講解的比較抽象,較難理解。筆者整理兩者異同點,同時配有標準案例進行說明。注意本文不是科普vuex和redux相關概念,相關知識內容可以在官方文件中檢視。Vuex (opens new window)Redux(opens new window)

  1. 異同點

    • 相同點

      • 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
          • vuexstate統一存放,方便理解;reduxstate依賴所有reducer的初始值
          • vuexgetter,目的是快捷得到state;redux沒有這層,react-redux mapStateToProps引數做了這個工作。
          • vuexmutation只是單純賦值(很淺的一層);reduxreducer只是單純設定新state(很淺的一層)。他倆作用類似,但書寫方式不同
          • vuexaction有較為複雜的非同步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的流向:
      1. view——>commit——>mutations——>state變化——>view變化(同步操作)
      2. 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的對比

相關文章