10、Vue3中Vuex从入门到实战:手写迷你Vuex,掌握前端状态管理核心
Vue3中Vuex从入门到实战:手写迷你Vuex,掌握前端状态管理核心
在Vue3项目开发中,组件化让代码复用和维护更高效,但跨组件、跨页面的数据共享却成了高频痛点——用户登录信息、全局权限、公共计数器等数据,如果靠组件传参层层传递,代码会变得混乱不堪。这时候,Vuex就成了前端状态管理的“大管家”,帮我们集中式管理共享数据。本文将从前端数据管理的痛点出发,带你吃透Vuex的核心用法,甚至手写一个迷你Vuex理解其底层原理。
一、前端数据管理:为什么需要Vuex?
现代Web应用由组件、数据、路由三大核心构成,组件内部的私有数据用ref/reactive管理即可,但共享数据的管理却需要更规范的方式。
我们先试想一个简单场景:用全局变量存储共享数据。
window._store ={}// 全局存储数据这种方式看似简单,但存在致命问题:window._store不是响应式的,修改数据后Vue组件无法自动更新视图。如果我们用Vue的响应式API包裹全局数据,并提供统一的修改方法,这就是Vuex的雏形——本质是“响应式的全局数据 + 规范化的修改规则”。
二、Vuex是什么?
Vuex是Vue官方的状态管理库,核心作用是集中式存储和管理应用中所有组件的共享状态。
可以做一个形象的类比:
- 小型项目(初创公司):组件私有数据(个人办公用品)随便用,无需规范;
- 中大型项目(成熟公司):共享数据(公共办公用品)需要“管家”统一管理,申请、修改都有规范——Vuex就是这个“管家”。
核心原则:组件私有数据用ref/reactive管理,跨组件/跨页面共享数据用Vuex管理。
三、Vuex快速上手:从安装到组件使用
1. 安装Vuex
Vue3需安装Vuex 4.x版本(@next标识):
npminstall vuex@next 2. 创建Store实例
在src/store/index.js中创建核心的Store,包含state(存储数据)和mutations(同步修改数据的方法):
import{ createStore }from'vuex'const store =createStore({// 定义共享数据state(){return{count:666}},// 定义修改数据的方法(唯一能修改state的地方)mutations:{add(state){ state.count++}}})exportdefault store 3. 注册Store到Vue应用
在项目入口src/main.js中注册,让所有组件能访问Store:
import{ createApp }from'vue'import App from'./App.vue'import store from'./store'const app =createApp(App) app.use(store)// 注册Vuex app.mount('#app')4. 组件中使用Vuex
新建src/components/Count.vue,通过useStore获取Store,用计算属性读取state,用commit触发mutation修改数据:
<template> <div @click="add">点击累加:{{ count }}</div> </template> <script setup> import { computed } from 'vue' import { useStore } from 'vuex' // 获取Store实例 const store = useStore() // 读取共享数据(计算属性保证响应式) const count = computed(() => store.state.count) // 触发mutation修改数据(不能直接修改store.state.count) function add() { store.commit('add') } </script> 四、手写迷你Vuex:理解底层原理
Vuex的核心原理其实很简单:响应式数据 + 依赖注入 + 规范化修改规则。我们用30行代码实现一个迷你版Vuex。
1. 实现核心逻辑(src/store/gvuex.js)
import{ inject, reactive }from'vue'// 依赖注入的唯一标识constSTORE_KEY='__store__'// 供组件获取Store实例的方法exportfunctionuseStore(){returninject(STORE_KEY)}// 创建Store实例的方法exportfunctioncreateStore(options){returnnewStore(options)}classStore{constructor(options){this.$options = options // 用reactive包裹state,让数据响应式this._state =reactive({data: options.state()})// 存储mutation方法this._mutations = options.mutations }// 对外暴露state(只读)getstate(){returnthis._state.data }// 触发mutation的方法commit=(type, payload)=>{const mutation =this._mutations[type] mutation &&mutation(this.state, payload)}// 供app.use(store)调用的安装方法(依赖注入)install(app){ app.provide(STORE_KEY,this)// 全局注入Store}}2. 替换官方Vuex使用迷你版
修改src/store/index.js,替换为手写的gvuex:
// import { createStore } from 'vuex'import{ createStore }from'./gvuex'const store =createStore({state(){return{count:666}},mutations:{add(state){ state.count++}}})exportdefault store 此时组件中使用useStore、commit的方式和官方Vuex完全一致,核心原理已复刻!
五、Vuex进阶:Getters和Actions
1. Getters:Vuex的“计算属性”
Getters用于对state做派生计算(类似组件的computed),比如实现count的双倍值:
// src/store/index.jsconst store =createStore({state(){return{count:666}},getters:{double(state){return state.count *2}},mutations:{add(state){ state.count++}}})组件中使用:
const double =computed(()=> store.getters.double)2. Actions:处理异步修改
Vuex规定mutation只能做同步操作,异步逻辑(如接口请求、延时)需放在actions中,再通过commit触发mutation:
// src/store/index.jsconst store =createStore({// ...其他配置actions:{// 异步累加(模拟1秒后修改)asyncAdd({ commit }){setTimeout(()=>{commit('add')},1000)}}})组件中通过dispatch触发action:
functionasyncAdd(){ store.dispatch('asyncAdd')}六、Vuex核心设计思想:数据流向
Vuex的核心是“单向数据流”,保证数据修改可追溯:
- 组件通过
dispatch触发action(异步)或直接commit触发mutation(同步); mutation是修改state的唯一入口,同步修改state;state更新后,组件通过计算属性读取最新值,视图自动更新。
七、下一代Vuex:Pinia
Vuex对TypeScript的类型推导支持不够友好,因此Vuex作者推出了Pinia(被称为“Vuex5”):
- 天生支持TypeScript,类型推断更友好;
- 无需嵌套模块,API更简洁;
- 完美兼容Vue Devtools;
- 可作为Vuex的替代方案,学习成本低。
八、总结
- 核心原则:私有数据用
ref/reactive,共享数据用Vuex; - 核心概念:
state:存储共享数据;mutation:同步修改state(唯一入口);getters:派生计算state;action:处理异步,内部调用mutation;
- 底层原理:响应式数据(
reactive) + 依赖注入(provide/inject) + 规范化修改规则; - 进阶选型:TypeScript项目优先考虑Pinia。
思考题
你的项目中哪些数据适合放在Vuex中管理?比如:
- 用户登录状态、用户名、权限;
- 全局主题、布局配置;
- 购物车数据、全局计数器;
- 多页面共享的筛选条件、分页信息。
欢迎在评论区交流你的项目实践~
📌 本文配套代码已整理,可结合Vue3项目实操,理解更深刻。如果觉得有帮助,欢迎点赞+收藏~