news 2026/9/19 20:50:10

Vuex 4 快速入门:从零构建你的第一个集中式状态管理 Store

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vuex 4 快速入门:从零构建你的第一个集中式状态管理 Store

Vuex 4 快速入门:从零构建你的第一个集中式状态管理 Store

【免费下载链接】vuex🗃️ Centralized State Management for Vue.js.项目地址: https://gitcode.com/gh_mirrors/vu/vuex

Vuex 是 Vue.js 官方的集中式状态管理模式与库,而docs/guide/index.md这篇入门指南回答了一个核心问题:如何创建并安装你的第一个 Vuex Store。本文以该入门指南为主体,结合本仓库(Vuex 4)的源码实现、单元测试与经典 counter 示例,系统讲解 Store 的两大设计原则、最简 Store 的完整搭建流程、store.state/store.commit的访问方式,以及组件内this.$store的用法,最终带你掌握在 Vue 3 应用中落地 Vuex 状态管理的完整实战路径。

什么是 Store:一切状态的中心容器

在每一个 Vuex 应用的中央,都站立着一个store(存储容器)。通俗地说,store 就是一个"盒子",它装着你的应用状态(state)——即应用中所有需要被共享、驱动视图渲染的数据源。

Vuex 的 store 与普通的全局对象(global object)有本质区别,体现在两条核心设计原则上:

  1. Vuex 的 store 是响应式的(reactive)。当 Vue 组件从 store 中读取状态时,如果 store 的状态发生了变化,组件会响应式地、高效地自动更新,无需手动触发重渲染。
  2. 你不能直接修改 store 中的状态。改变状态的唯一途径,是显式地提交(commit)一个 mutation(变更)。这一约定保证了每一次状态变更都能留下可追踪的记录,并让诸如日志记录、状态快照、时间旅行调试(time travel debugging)等工具成为可能。

从源码层面看,这两条原则有非常具体的落点。Vuex 4 中 Store 的响应式由 Vue 3 的reactiveAPI 承载:在 src/store-util.js 的resetStoreState中,store 的内部状态被包装为reactive({ data: state }),并通过store.state的 getter 暴露出来(见 src/store.js);而"只能通过 mutation 修改状态"则由_withCommit标志位与严格模式守护,commit()内部会先将this._committing置为true,再依次执行所有 mutation handler(见 src/store.js 与 src/store.js)。

在继续阅读之前需要说明:本文代码示例采用 ES2015 语法(包括importconst、箭头函数等),这也是 Vuex 官方文档余下所有章节的统一风格。

准备工作:安装 Vuex 4

在创建第一个 store 之前,需要先安装 Vuex。由于本仓库是 Vuex 4(面向 Vue 3 的版本),官方提供了多种安装方式,详见 安装指南:

通过包管理器安装(推荐):

# npm npm install vuex@next --save # yarn yarn add vuex@next --save

通过 CDN 直接引入:

在 Vue 之后引入vuex的构建文件,它会自动完成安装:

<script src="/path/to/vue.js"></script> <script src="/path/to/vuex.js"></script>

CDN 链接始终指向 NPM 上的最新 release;如需指定版本,可使用https://unpkg.com/vuex@4.0.0/dist/vuex.global.js这类带版本号的 URL。

使用开发版构建:

如果你希望使用最新的开发构建,则需要克隆 Vuex 源码仓库并自行构建:

git clone https://github.com/vuejs/vuex.git node_modules/vuex cd node_modules/vuex yarn yarn build

安装完成后,即可通过import { createStore } from 'vuex'引入createStore工厂函数。在 src/index.js 中可以看到,Vuex 4 对外导出了createStoreStorestoreKeyuseStoremapStatemapGettersmapActionsmapMutationscreateNamespacedHelperscreateLogger等全部公共 API。

创建最简 Store:state 与 mutations

创建一个 Vuex store 非常简单直接:只需提供一个初始状态对象和若干mutations(变更)。下面是最小的完整示例:

import { createApp } from 'vue' import { createStore } from 'vuex' // 创建一个新的 store 实例。 const store = createStore({ state () { return { count: 0 } }, mutations: { increment (state) { state.count++ } } }) const app = createApp({ /* your root component */ }) // 将 store 实例作为插件安装 app.use(store)

注意这里有两个关键细节:

  • state是一个返回对象的函数,而不是一个普通对象字面量。在 examples/classic/counter/store.js 中则直接使用了对象字面量写法(const state = { count: 0 }),两种写法在根 store 中都可用,但函数形式在多模块场景下能避免状态对象被多个模块共享引用。
  • mutations中的每个 handler 接收state作为第一个参数,并在其中直接修改状态——例如state.count++

createStore只是new Store(options)的语法糖(见 src/store.js)。Store 构造器会依次完成:初始化内部注册表(_actions_mutations_wrappedGetters_modules等)、递归安装所有模块、初始化响应式状态、最后应用插件(见 src/store.js)。

读取状态与提交变更:store.state 与 store.commit

store 创建完成后,你就可以通过store.state访问状态对象,并通过store.commit触发状态变更:

store.commit('increment') console.log(store.state.count) // -> 1

这段代码的执行链路在源码中非常清晰:store.commit('increment')会在_mutations表中查找'increment'对应的 handler 列表,并在_withCommit的保护下依次执行,随后通知所有订阅者(subscribers)(见 src/store.js)。commit还支持对象风格的调用,这在 test/unit/store.spec.js 中有专门用例验证:

store.commit({ type: TEST, amount: 2 }) // 等价于 store.commit(TEST, { amount: 2 })

这一写法由 src/store-util.js 中的unifyObjectStyle统一解析,它同时服务于commitdispatch,并且在开发环境下会对非字符串的 type 抛出断言错误(见 test/unit/store.spec.js 的对应测试)。

为什么必须 commit 而不是直接改store.state.count

入门指南强调:我们选择提交 mutation 而非直接修改store.state.count,是因为我们想显式地追踪它。这个简单的约定让代码意图更加明确——阅读代码时,你能一眼看出状态是在哪里、因为什么而改变的。更重要的是,它为工具链打开了大门:可以记录每一次 mutation、拍摄状态快照、甚至实现时间旅行调试

在仓库中,mutation 的"可追踪性"有两个具体实现:其一,commit()执行后会调用this._subscribers.slice().forEach(sub => sub(mutation, this.state)),将 mutation 对象与最新状态广播给订阅者(见 src/store.js),这正是 devtool 插件 与日志插件工作的基础;其二,在开发模式下,_withCommit标志位配合严格模式会在状态被非法修改时给出明确报错(见 src/store-util.js 的enableStrictMode)。

在 Vue 组件中使用 store:this.$store

在 Vue 组件中,你可以通过this.$store访问到 store 实例,然后像下面这样在组件方法中提交 mutation:

methods: { increment() { this.$store.commit('increment') console.log(this.$store.state.count) } }

this.$store的注入发生在Store.install方法中:当执行app.use(store)时,Vuex 会通过app.provide(injectKey || storeKey, this)将 store 提供给整个组件树,同时将其挂载到app.config.globalProperties.$store上(见 src/store.js),这就是任意层级的组件都能拿到this.$store的原因。默认的storeKey就是字符串'store'(见 src/injectKey.js)。

用计算属性读取响应式状态

在组件中使用 store 状态的推荐方式是:在 computed 属性(计算属性)中返回该状态,因为 store 的状态本身就是响应式的;而触发变更则是在组件方法中提交 mutation:

computed: { count () { return this.$store.state.count } }

这背后的响应式链路是:store 状态被reactive()包装,组件中的计算属性读取它时建立依赖,一旦 mutation 修改了状态,依赖它的计算属性会自动重新求值,进而驱动视图更新。

仓库中的 examples/classic/counter/Counter.vue 给出了一个完整的实战范本:模板中直接用{{ $store.state.count }}渲染状态,通过mapGettersmapActions辅助函数把 getter 映射为计算属性、把 action 映射为方法;对应的 examples/classic/counter/app.js 展示了标准的挂载流程(createApp(Counter)app.use(store)app.mount('#app'))。完整的 counter store(含incrementdecrementincrementIfOddincrementAsync等动作)见 examples/classic/counter/store.js。

背后的原理:响应式与可追踪性的源码印证

入门指南反复强调的两个特性,可以在源码中找到完整印证:

响应式(Reactive)。resetStoreState使用reactive({ data: state })包装根状态,并将 getters 包装为基于computed的惰性缓存属性——为避免 getter 在组件卸载时被销毁,还特意用effectScope承载这些 computed(见 src/store-util.js)。这就是"组件读取 store 状态后能响应式高效更新"的实现基础。

可追踪(Trackable)。除了commit广播订阅者之外,store 还提供了subscribesubscribeAction方法(见 src/store.js),让插件可以监听每一次 mutation 与 action 的生命周期;replaceState(src/store.js)则在_withCommit保护下显式替换整个状态树——这正是状态快照与时间旅行调试能力得以存在的前提。

小结与下一步

入门指南用一句话总结了 Vuex 的使用心智模型:在组件中使用 store 状态,就是在计算属性中返回该状态;触发变更,就是在组件方法中提交 mutation。围绕 store 的两个核心特性——响应式读取、显式提交变更——你已经可以写出第一个可用的 Vuex 应用。

入门之后,官方指南按以下顺序深入讲解每个核心概念,你可以顺着阅读:

  • State(状态)——在组件与mapState中访问状态的完整方式
  • Getters(派生状态)——像计算属性一样对 store 状态做派生与复用
  • Mutations(变更)——提交载荷(payload)、对象风格提交与响应式规则
  • Actions(动作)——异步操作与组合 dispatch
  • Modules(模块)——把大型 store 拆分为命名空间模块
  • Plugins(插件)——订阅 mutation/action 实现日志、持久化等能力
  • Strict Mode(严格模式)——强制所有状态变更必须发生在 mutation 中
  • 组合式 API 用法——在<script setup>中通过useStore消费 store
  • TypeScript 支持 与 从 Vuex 3 迁移到 4

完整的 API 说明可查阅 API 参考文档。此外,本仓库的 examples/classic 与 examples/composition 目录下还提供了 counter、chat、shopping-cart、todomvc 等可直接运行参考的完整示例应用,可以作为你动手实践的最佳样板。

【免费下载链接】vuex🗃️ Centralized State Management for Vue.js.项目地址: https://gitcode.com/gh_mirrors/vu/vuex

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 20:46:26

Codex 下载与本地部署:命令行 AI 编码助手安装与模型接入避坑

上周有位同事在群里发了一张终端截图&#xff0c;满屏红字&#xff0c;最扎眼的是接口返回 404&#xff0c;说找不到/responses这个路径。他为了把 Codex 跑起来折腾了整整两天&#xff0c;中间重装过 Node&#xff0c;换过三个模型&#xff0c;最后发现只是配置文件里少写了一…

作者头像 李华
网站建设 2026/9/19 20:45:15

Ruffle 桌面版 SWF 播放器:3 步打开老 Flash 文件

Ruffle 桌面版 SWF 播放器&#xff1a;3 步打开老 Flash 文件 【免费下载链接】ruffle A Flash Player emulator written in Rust 项目地址: https://gitcode.com/GitHub_Trending/ru/ruffle 浏览器里的 Flash 插件早已停用&#xff0c;你硬盘里的 .swf 老游戏却还在。R…

作者头像 李华
网站建设 2026/9/19 20:43:42

Cursor 的 Agent 模式要分析整个代码库?TaoToken 这样改 Base URL

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 20:42:49

4款AI论文写作工具评测与原创度提升技巧

1. 为什么我们需要AI论文写作工具&#xff1f;作为一名在学术圈摸爬滚打多年的研究者&#xff0c;我深知论文写作的痛苦。从选题到文献综述&#xff0c;从实验设计到结果分析&#xff0c;每个环节都需要耗费大量时间和精力。最让人头疼的是&#xff0c;辛辛苦苦写出来的内容&am…

作者头像 李华