Vue和React对比学习之状态管理 (Vuex和Redux)

简介: 状态管理

简介

VuexRedux应该是我们前端开发用得最多的两个状态管理库了。那么这两者到底有哪些相同点和不同点呢?今天我们再来对比总结下。

希望通过这种对比方式的学习能让我们学习的时候印象更深刻,希望能够帮助到大家。

安装

Vuex直接安装就可以使用

npm i vuex

Redux在React中使用还需要使用React-Redux

React中单使用Redux是不行的,还需要借助React-ReduxReact-Redux类似一个桥梁将ReduxReact连接起来。

npm i redux react-redux

整体结构

Vuex主要分为四大块

Vuex中,主要分为state、getters、mutations、actions四大块。

  1. state定义状态。
  2. getters是状态的计算属性,状态改变自动会重新计算。
  3. mutation用来同步修改state。也是唯一能修改state的地方。
  4. actions用来进行异步操作,并且还可以提交mutationaction
// module1.js

{
 // 状态
 state: {
   userinfo: {}
 },
 
 // 计算属性,状态改变自动会重新计算
 gertters: {
   getterUserInfo(state, getters, rootState, rootGetters) {
     return state.userinfo
   }
 },
 
 // 同步修改state
 mutations: {
   setUserInfo(state, payload) {
     state.userinfo = payload
   }
 },
 
 // 进行异步操作,每个action的返回值都是一个promise
 // 还可以提交mutation或action
 actions: {
   async getUserInfoAction({ dispatch, commit, state, rootState, getters, rootGetters }, payload) {
     // 异步请求获取结果
     const response = await fetch(
        `https://jsonplaceholder.typicode.com/todos/${payload}`
      );
     const result = response.json()
     // 提交 mutation
     commit(setUserInfo, result)
     
     // 返回值会被promise包裹
     return result
   }
 },
}

store达到一定规模后我们还会启用modulesnamespaced来进行更精细化的管理。

当启用modulesstore总体目录如下

store
    ├── modules
    │   ├── module1.js
    │   └── module2.js
    └── index.js

根模块

// index.js

{
 // 根状态
 state: {
   userinfo: {}
 },
 
 // 根getters
 gertters: {},
 
 // 根mutations
 mutations: {},
 
 // 根actions
 actions: {},
 
 // 模块,当系统庞大后一般会启用模块功能
 modules: {
   module1: module1,
   module2: module2
 },
}

当只启用了module后,state会通过模块来获取,上面的例子this.$store.state.userinfo获取用户信息会变为this.$store.state.module1.userinfo。但是getters、mutations、actions的获取方式不受影响。

当启用了module并且子模块启用了namespaced,则getters、mutations、actions也会通过模块来获取。上面的例子this.$store.getter.getterUserInfo会变为this.$store.getter['module1/getterUserInfo']mutations、actions也是类似,会加上模块名。

// module1.js

{
  // 命名空间,当设置为true后,getters mutations actions都会按模块来处理
  namespaced: true
}

当启用namespaced后,该模块的action只能提交本模块的mutationaction,不能提交其它模块的mutationaction,如果要提交需要传递第三个参数root: true

commit("其它模块的mutation", payload, { root: true });
dispatch("其它模块的action", payload, { root: true });

当启用namespaced后,如果想创建全局的action,需要使用对象形式的写法,并传递root: true

// 注册非命名空间的action
// root: true,
setGlobalGoodsAction: {
  root: true,
  handler: ({ commit }) => {
    commit("setGoodsNameMutation", "我是全局action,提交我不用带命名空间");
  },
}

这个action就会被注册到根模块下,不需要通过模块名来获取。

Redux主要分为三大块

Redux中主要分为state、actions、reducers三大块

state // 定义状态,一般定义在reducer中

actions // 传递type和payload参数

reducers // 改变 state 的唯一方法,必须为纯函数,判断 action 的type相应更新state。每次 reducer 都是返回一个全新的 state。

Redux没有Vuex那么聚合,各个模块分离的比较散,都是单独的文件,不用写在一个文件中。

action1.js

export const setUserInfoAction(payload) {
  return {
    type: 'setuserinfo',
    payload
  }
}

reducer1.js,在Redux中,state一般会定义在reducer中。

const initialState = { userinfo: {}}

export default function(state=initialState, action) {
  switch(action.type) {
    case 'setuserinfo':
      return {...state, userinfo: action.payload}
    default:
      return state
  }
}

store达到一定规模后我们会创建多个reducer然后使用combineReducers()来讲他们组合起来。

Reduxstore总体目录如下

store
    ├── actions
    │   ├── action1.js
    │   └── action2.js
    ├── reducers
    │   ├── reducer1.js
    │   └── reducer2.js
    ├── types.js
    └── index.js

创建

Vue通过createStore方法创建store

通过createStore方法并传递根模块创建store实例。

import { createStore } from "vuex";

export default createStore({
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {
    // 这面是子模块
  }
})

然后通过Vueuse方法,以插件形式进行使用。

import { createApp } from "vue";

const app = createApp(App);

app.use(store).mount("#app");

React通过createStore方法创建store

React通过ReduxcreateStore方法传递所有的reducers创建store

import { createStore } from "redux";
const store = createStore(redicers);

然后通过React-ReduxProvider组件传递store进去,将ReactRedux连接在一起。

import { Provider } from "react-redux";

<Provider store={store}>
  <App />
</Provider>

使用

Vue中可以直接使用

// vue2
// this.$store.state // 获取state
// this.$store.getter // 获取getter
// this.$store.commit() // 提交mutation
// this.$store.dispatch() // 提交action

// vue3
import {useStore} from 'vuex'
const store = useStore()

// store.state // 获取state
// store.getter // 获取getter
// store.commit() // 提交mutation
// store.dispatch() // 提交action

React中需要借助React-Redux的connect方法

// 类组件
// 通过react-redux的connect方法参数mapStateToProps将state定义到组件的props属性上。
mapStateToProps(state) {
  return {
    userinfo: state.reducer1.userinfo
  }
}
// 通过react-redux的connect方法参数mapDispatchToProps将dispatch方法传递进来。
mapDispatchToProps(dispatch) {
  return {
    handleSetUserInfo() {
      dispatch(getUserInfoAction(1))
    }
  }
}

// 函数组件
// 函数组件通过react-redux的useSelector和useDispatch两个hook
const userinfo = useSelector((state) => state.reducer1.userinfo);

const dispatch = useDispatch();
dispatch(getUserInfoAction(1))

异步方案

异步一般就是我们向后端发送请求获取数据的过程。

Vuex直接支持异步

Vuex中,我们的异步操作可以直接定义在action中,当异步有了结果再提交mutation来同步修改state

Redux需要借助中间件

Redux中因为action只能返回普通的对象所以是不支持直接使用异步的。如果要使用异步,需要借助redux-thunk、redux-promise、redux-saga等第三方中间件。

具体使用可以查阅笔者前面写的Redux 异步数据流方案对比(redux-thunk、redux-promise、redux-saga),这里就不再细说了。

数据流

在数据流方面,VuexRedux都是单仓库单向数据流。也就是数组仓库store只会有一个,并且都只能在触发相应action后,在reducermutaion里面才能修改state,是一个单向数据流。

image.png

VuexRedux都是只能在特定地方修改stateVuex只能在mutation中修改,Redux只能在reducer中修改。

Redux中不能直接修改原statereducer必须是纯函数,每次返回新的state。在Vuexmutation里面是可以对state直接修改的。

同步数据流

Vuex中同步数据流是commit mutation -> 进入到mutation方法直接修改state

Redux中同步数据流是dispatch action -> 进入到reducer匹配type进行相应处理返回新的state

异步数据流

Vuex中异步数据流是dispatch action -> 进入到action进行异步请求 -> 请求有了结果commit mutation -> 进入到mutation方法修改state

Redux中异步数据流是dispatch action -> 进入到异步中间件进行异步请求 ->请求有了结果进入reducer匹配type进行相应处理返回新的state

总结

  1. Vuex安装后直接使用,ReduxReact中使用还需要借助React-Redux
  2. Vuexstate、getters、mutations、actions集中在一个文件,并各司其职。Redux相对来说较为分散,state、actions、reducers定义在不同的文件中,对于初学者来说可能没那么好理解。但是可以使用Redux Toolkit来简化Redux的使用,使用Redux Toolkit后就会有在使用Vuex的感觉,想了解更多的话可以看看笔者前面写的对比React-Redux看看Redux Toolkit有哪些优点
  3. Vuex内可以直接使用异步,但是Redux需要借助redux-thunk、redux-promise、redux-saga等中间件。
  4. Vuexmutation里面是直接修改state,但是Reduxreducer里面每次必须返回新的state
  5. Vuex里面是支持getter计算属性的,但是Redux不支持。

系列文章

Vue和React对比学习之生命周期函数(Vue2、Vue3、老版React、新版React)

Vue和React对比学习之组件传值(Vue2 12种、Vue3 9种、React 7种)

Vue和React对比学习之Style样式

Vue和React对比学习之Ref和Slot

Vue和React对比学习之Hooks

Vue和React对比学习之路由(Vue-Router、React-Router)

Vue和React对比学习之状态管理 (Vuex和Redux)

Vue和React对比学习之条件判断、循环、计算属性、属性监听

后记

感谢小伙伴们的耐心观看,本文为笔者个人学习笔记,如有谬误,还请告知,万分感谢!如果本文对你有所帮助,还请点个关注点个赞~,您的支持是笔者不断更新的动力!

相关文章
|
2月前
|
存储 JavaScript 前端开发
掌握现代Web开发的基石:深入理解React与Redux
【10月更文挑战第14天】掌握现代Web开发的基石:深入理解React与Redux
39 0
|
1月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
41 1
vue学习第一章
|
1月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
30 1
|
1月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
38 1
vue学习第四章
|
1月前
|
JavaScript 前端开发 算法
vue学习第7章(循环)
欢迎来到瑞雨溪的博客,一名热爱JavaScript和Vue的大一学生。本文介绍了Vue中的v-for指令,包括遍历数组和对象、使用key以及数组的响应式方法等内容,并附有综合练习实例。关注我,将持续更新更多优质文章!🎉🎉🎉
25 1
vue学习第7章(循环)
|
1月前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
30 1
vue学习第九章(v-model)
|
1月前
|
JavaScript 前端开发 开发者
vue学习第十章(组件开发)
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文深入讲解Vue组件的基本使用、全局与局部组件、父子组件通信及数据传递等内容,适合前端开发者学习参考。持续更新中,期待您的关注!🎉🎉🎉
44 1
vue学习第十章(组件开发)
|
1月前
|
JavaScript 前端开发
vue学习第十一章(组件开发2)
欢迎来到我的博客,我是瑞雨溪,一名自学前端两年半的大一学生,专注于JavaScript与Vue。本文介绍Vue中的插槽(slot)使用方法,包括基本插槽、具名插槽及作用域插槽,帮助你在组件开发中实现内容的灵活定制。如果你觉得有帮助,请关注我,持续更新中!🎉🎉🎉
23 1
vue学习第十一章(组件开发2)
|
1月前
|
监控 JavaScript 前端开发
vue学习第十二章(生命周期)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。本文深入探讨了Vue实例的生命周期,从初始化到销毁各阶段的关键钩子函数及其应用场景,帮助你更好地理解Vue的工作原理。如果你觉得有帮助,欢迎关注我,将持续分享更多优质内容!🎉🎉🎉
29 1
vue学习第十二章(生命周期)
|
1月前
|
存储 JavaScript 前端开发
vue3的脚手架模板你真的了解吗?里面有很多值得我们学习的地方!
【10月更文挑战第21天】 vue3的脚手架模板你真的了解吗?里面有很多值得我们学习的地方!
vue3的脚手架模板你真的了解吗?里面有很多值得我们学习的地方!