vue和react和uniapp的状态管理分别是什么,并且介绍和怎么使用

一、Vue 的状态管理

Vue 的状态管理方案主要有 Vuex (Vue2 主流)和 Pinia(Vue3 官方推荐,Vuex 的继任者),用于管理组件间共享的状态(如用户信息、全局配置等)。

1. Vuex(适用于 Vue2)

核心概念

  • State:存储全局状态的对象(唯一数据源)。
  • Mutation:修改状态的唯一方式(同步操作),必须是纯函数。
  • Action:处理异步操作(如接口请求),通过提交 Mutation 修改状态。
  • Getter:类似计算属性,用于派生状态(可缓存结果)。
  • Module:将 store 拆分为多个模块(避免单一状态树过于庞大)。

使用步骤

① 安装:npm install vuex --save

② 创建 store(src/store/index.js

复制代码
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  // 状态
  state: {
    count: 0,
    user: null
  },
  // 同步修改状态
  mutations: {
    increment(state) {
      state.count++
    },
    setUser(state, userInfo) {
      state.user = userInfo
    }
  },
  // 异步操作
  actions: {
    // 模拟异步请求用户信息
    fetchUser({ commit }) {
      return new Promise(resolve => {
        setTimeout(() => {
          const user = { name: '张三', age: 20 }
          commit('setUser', user) // 提交 mutation 修改状态
          resolve(user)
        }, 1000)
      })
    }
  },
  // 派生状态
  getters: {
    doubleCount(state) {
      return state.count * 2
    }
  }
})

export default store

③ 在 main.js 中挂载:

复制代码
import Vue from 'vue'
import App from './App.vue'
import store from './store'

new Vue({
  store, // 挂载后可通过 this.$store 访问
  render: h => h(App)
}).$mount('#app')

④ 在组件中使用:

复制代码
<template>
  <div>
    <p>计数:{{ $store.state.count }}</p>
    <p>翻倍计数:{{ $store.getters.doubleCount }}</p>
    <button @click="handleIncrement">+1</button>
    <button @click="handleFetchUser">获取用户</button>
  </div>
</template>

<script>
export default {
  methods: {
    handleIncrement() {
      this.$store.commit('increment') // 调用 mutation
    },
    async handleFetchUser() {
      await this.$store.dispatch('fetchUser') // 调用 action
      console.log(this.$store.state.user) // { name: '张三', ... }
    }
  }
}
</script>
2. Pinia(适用于 Vue3,推荐)

Pinia 简化了 Vuex 的设计(移除 Mutation,支持 Vue3 的 Composition API),更轻量、易上手。

核心概念

  • State:存储状态(可直接修改,无需 mutation)。
  • Action:支持同步 / 异步操作,直接修改 state。
  • Getter:派生状态(同 Vuex)。

使用步骤

① 安装:npm install pinia --save

② 创建 store(src/store/index.js

复制代码
import { defineStore } from 'pinia'

// 定义 store(id 需唯一)
export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    user: null
  }),
  getters: {
    doubleCount: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++ // 直接修改 state
    },
    async fetchUser() {
      // 模拟异步请求
      const user = await new Promise(resolve => {
        setTimeout(() => resolve({ name: '李四', age: 22 }), 1000)
      })
      this.user = user // 直接修改 state
    }
  }
})

③ 在 main.js 中挂载:

复制代码
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'

const app = createApp(App)
app.use(createPinia()) // 挂载 Pinia
app.mount('#app')

④ 在组件中使用(支持 Options API 和 Composition API):

复制代码
<template>
  <div>
    <p>计数:{{ counterStore.count }}</p>
    <p>翻倍计数:{{ counterStore.doubleCount }}</p>
    <button @click="counterStore.increment">+1</button>
    <button @click="counterStore.fetchUser">获取用户</button>
  </div>
</template>

<script setup>
import { useCounterStore } from './store'
const counterStore = useCounterStore() // 引入 store
</script>

二、React 的状态管理

React 本身没有官方状态管理库,需依赖第三方工具。主流方案有:Redux (经典)、Redux Toolkit (Redux 简化版)、Context + useReducer (轻量场景),以及 ZustandRecoil 等新兴库。

1. Redux Toolkit(推荐,简化 Redux 用法)

Redux 核心是 "单一状态树",通过 Action(描述操作)和 Reducer(处理状态变更)管理状态。Redux Toolkit 简化了 Redux 的模板代码。

核心概念

  • Store:存储全局状态的容器(唯一)。
  • Slice:包含 statereduceraction 的独立模块。
  • Action:描述 "要做什么" 的普通对象(由 createSlice 自动生成)。
  • Reducer:根据 action 处理状态变更的纯函数。

使用步骤

① 安装:npm install @reduxjs/toolkit react-redux --save

② 创建 slice(src/store/counterSlice.js

复制代码
import { createSlice } from '@reduxjs/toolkit'

// 初始状态
const initialState = {
  count: 0,
  user: null
}

// 创建 slice(自动生成 action 和 reducer)
const counterSlice = createSlice({
  name: 'counter', // 模块名
  initialState,
  reducers: {
    // 同步修改
    increment: (state) => {
      state.count++ // Redux Toolkit 内部使用 Immer 库,支持"直接修改"写法
    },
    setUser: (state, action) => {
      state.user = action.payload // action.payload 为传入的参数
    }
  },
  // 处理异步 action(需配合 createAsyncThunk)
  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => {
        state.loading = true
      })
      .addCase(fetchUser.fulfilled, (state, action) => {
        state.user = action.payload
        state.loading = false
      })
  }
})

// 导出同步 action
export const { increment, setUser } = counterSlice.actions

// 定义异步 action(使用 createAsyncThunk)
import { createAsyncThunk } from '@reduxjs/toolkit'
export const fetchUser = createAsyncThunk(
  'user/fetch', // action 类型名
  async () => {
    // 模拟接口请求
    const res = await new Promise(resolve => {
      setTimeout(() => resolve({ name: '王五', age: 25 }), 1000)
    })
    return res
  }
)

// 导出 reducer
export default counterSlice.reducer

③ 创建 store(src/store/index.js):

复制代码
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './counterSlice'

// 配置 store(自动集成中间件,无需手动配置)
export const store = configureStore({
  reducer: {
    counter: counterReducer // 注册 slice 的 reducer
  }
})

④ 在入口文件挂载(src/index.js):

复制代码
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { Provider } from 'react-redux' // 提供 store 上下文
import { store } from './store'

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <Provider store={store}>
    <App />
  </Provider>
)

⑤ 在组件中使用:

复制代码
import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux' //  hooks 访问 store
import { increment, fetchUser } from './store/counterSlice'

function Counter() {
  // 获取状态
  const { count, user } = useSelector(state => state.counter)
  // 获取 dispatch 方法
  const dispatch = useDispatch()

  return (
    <div>
      <p>计数:{count}</p>
      <button onClick={() => dispatch(increment())}>+1</button>
      <button onClick={() => dispatch(fetchUser())}>获取用户</button>
      {user && <p>用户:{user.name}</p>}
    </div>
  )
}

export default Counter
2. Context + useReducer(轻量场景)

对于简单项目,可使用 React 内置的 ContextuseReducer 实现状态管理,无需引入第三方库。

复制代码
import React, { createContext, useReducer, useContext } from 'react'

// 1. 创建 Context
const CounterContext = createContext()

// 2. 定义 reducer(处理状态变更)
function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 }
    case 'SET_USER':
      return { ...state, user: action.payload }
    default:
      return state
  }
}

// 3. 创建 Provider 组件(提供状态和 dispatch)
export function CounterProvider({ children }) {
  const [state, dispatch] = useReducer(reducer, { count: 0, user: null })
  return (
    <CounterContext.Provider value={{ state, dispatch }}>
      {children}
    </CounterContext.Provider>
  )
}

// 4. 自定义 hook 简化使用
function useCounter() {
  return useContext(CounterContext)
}

// 5. 在组件中使用
function Counter() {
  const { state, dispatch } = useCounter()
  return (
    <div>
      <p>计数:{state.count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+1</button>
    </div>
  )
}

// 6. 在入口组件中包裹
function App() {
  return (
    <CounterProvider>
      <Counter />
    </CounterProvider>
  )
}

三、UniApp 的状态管理

UniApp 基于 Vue 语法,因此状态管理方案与 Vue 高度兼容,主流方案有:

  • Vuex/Pinia:同 Vue 的使用方式(推荐,适合复杂项目)。
  • 全局变量 :通过 getApp().globalData 定义全局变量(适合简单场景)。
  • 事件总线 :通过 uni.$on/uni.$emit 实现组件通信(适合跨组件消息传递)。
1. Vuex(UniApp 中最常用)

使用方式与 Vue2 中的 Vuex 一致,仅需注意 UniApp 的项目结构。

使用步骤

① 在项目根目录创建 store 文件夹,新建 index.js

复制代码
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    token: '',
    userInfo: null
  },
  mutations: {
    setToken(state, token) {
      state.token = token
      // 可同步到本地存储(持久化)
      uni.setStorageSync('token', token)
    }
  },
  actions: {
    login({ commit }, userData) {
      // 模拟登录接口
      return new Promise(resolve => {
        setTimeout(() => {
          const token = 'xxx-token-xxx'
          commit('setToken', token)
          resolve(token)
        }, 1000)
      })
    }
  }
})

export default store

② 在 main.js 中挂载:

复制代码
import Vue from 'vue'
import App from './App'
import store from './store'

Vue.prototype.$store = store // 挂载到 Vue 原型

const app = new Vue({
  ...App,
  store
})
app.$mount()

③ 在页面 / 组件中使用:

复制代码
<template>
  <view>
    <button @click="handleLogin">登录</button>
  </view>
</template>

<script>
export default {
  methods: {
    async handleLogin() {
      const token = await this.$store.dispatch('login', { username: 'test' })
      console.log('登录成功,token:', token)
      console.log('全局状态中的 token:', this.$store.state.token)
    }
  }
}
</script>
2. 全局变量(简单场景)

通过 getApp().globalData 定义全局变量,适合无需复杂逻辑的简单状态。

示例

① 在 App.vue 中定义:

复制代码
onLaunch() {
  // 初始化全局数据
  getApp().globalData = {
    theme: 'light',
    version: '1.0.0'
  }
}

② 在页面中使用:

复制代码
<template>
  <view>当前主题:{{ theme }}</view>
</template>

<script>
export default {
  data() {
    return {
      theme: ''
    }
  },
  onLoad() {
    // 读取全局变量
    this.theme = getApp().globalData.theme
    // 修改全局变量
    getApp().globalData.theme = 'dark'
  }
}
</script>

总结

  • Vue:Vue2 用 Vuex,Vue3 推荐 Pinia(更简洁,支持 Composition API)。
  • React:复杂项目用 Redux Toolkit,简单项目用 Context + useReducer。
  • UniApp:优先使用 Vuex/Pinia(与 Vue 生态一致),简单场景可用全局变量或事件总线。

状态管理的核心是 "集中管理共享状态",选择方案时需根据项目复杂度和团队熟悉度决定。