Vuex 超详细使用教程(从入门到精通)

一、Vuex 是什么?

Vuex 是专门为 Vue.js 设计的状态管理库,它采用集中式存储管理应用的所有组件的状态。简单来说,Vuex 就是一个"全局变量仓库",所有组件都可以从这里获取数据或修改数据。

二、为什么要用 Vuex?

当你的 Vue 应用变得复杂时,组件之间的数据共享和通信会变得困难。Vuex 解决了以下问题:

  1. 多个组件共享同一状态

  2. 不同组件需要变更同一状态

  3. 组件深层嵌套时的数据传递

三、安装与基础配置

1. 安装 Vuex

npm install vuex --save
# 或
yarn add vuex

2. 创建 Store

在项目中创建 store/index.js 文件:

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex) // 告诉 Vue 使用 Vuex// 创建 Vuex Store 实例
const store = new Vuex.Store({// 在这里配置 Vuex
})export default store

3. 在 Vue 实例中引入

在 main.js 中:

import Vue from 'vue'
import App from './App.vue'
import store from './store' // 导入我们创建的 storenew Vue({store, // 注入 storerender: h => h(App)
}).$mount('#app')

四、核心概念详解

1. State - 状态仓库

State 就是存储数据的地方,相当于组件中的 data。

const store = new Vuex.Store({state: {count: 0,user: {name: '张三',age: 25},todos: [{ id: 1, text: '学习Vuex', done: true },{ id: 2, text: '写项目', done: false }]}
})
在组件中访问 State

方法1:直接通过 this.$store.state 访问

computed: {count() {return this.$store.state.count},userName() {return this.$store.state.user.name}
}

方法2:使用 mapState 辅助函数

import { mapState } from 'vuex'export default {computed: {// 数组形式 - 同名映射...mapState(['count', 'user']),// 对象形式 - 可自定义名称...mapState({myCount: 'count',currentUser: state => state.user})}
}

2. Getters - 计算属性

Getters 相当于 Store 的计算属性,用于从 state 中派生出一些状态。

const store = new Vuex.Store({state: {todos: [{ id: 1, text: '学习Vuex', done: true },{ id: 2, text: '写项目', done: false }]},getters: {// 获取已完成的任务doneTodos: state => {return state.todos.filter(todo => todo.done)},// 获取未完成的任务数量undoneTodosCount: (state, getters) => {return state.todos.length - getters.doneTodos.length},// 通过ID获取特定任务getTodoById: state => id => {return state.todos.find(todo => todo.id === id)}}
})
在组件中使用 Getters

方法1:直接通过 this.$store.getters 访问

computed: {doneTodos() {return this.$store.getters.doneTodos},todo() {return this.$store.getters.getTodoById(2)}
}

方法2:使用 mapGetters 辅助函数

import { mapGetters } from 'vuex'export default {computed: {// 数组形式 - 同名映射...mapGetters(['doneTodos', 'undoneTodosCount']),// 对象形式 - 可自定义名称...mapGetters({doneList: 'doneTodos',todo: 'getTodoById'})},methods: {getTodo(id) {return this.todo(id) // 使用带参数的getter}}
}

3. Mutations - 修改状态

Mutations 是修改 State 的唯一途径,每个 mutation 都有一个字符串的 事件类型 (type) 和一个 回调函数 (handler)

const store = new Vuex.Store({state: {count: 1},mutations: {// 基本形式increment(state) {state.count++},// 带参数的形式incrementBy(state, payload) {state.count += payload.amount},// 对象风格的提交decrement(state, { amount }) {state.count -= amount}}
})
提交 Mutations

方法1:直接提交

methods: {increment() {this.$store.commit('increment')},addFive() {// 提交带参数的mutationthis.$store.commit('incrementBy', { amount: 5 })// 对象风格提交this.$store.commit({type: 'incrementBy',amount: 5})}
}

方法2:使用 mapMutations 辅助函数

methods: {increment() {this.$store.commit('increment')},addFive() {// 提交带参数的mutationthis.$store.commit('incrementBy', { amount: 5 })// 对象风格提交this.$store.commit({type: 'incrementBy',amount: 5})}
}
import { mapMutations } from 'vuex'export default {methods: {// 数组形式 - 同名映射...mapMutations(['increment', 'incrementBy']),// 对象形式 - 可自定义名称...mapMutations({add: 'increment',addAmount: 'incrementBy'}),// 使用方法addFive() {this.addAmount({ amount: 5 })}}
}
重要规则:
  1. Mutation 必须是同步函数

  2. 不要在 mutation 中执行异步操作

  3. 建议使用常量替代 Mutation 事件类型(大型项目)

4. Actions - 处理异步操作

Actions 类似于 mutations,不同在于:

  • Actions 提交的是 mutations,而不是直接变更状态

  • Actions 可以包含任意异步操作

const store = new Vuex.Store({state: {count: 0},mutations: {increment(state) {state.count++}},actions: {// 基本形式incrementAsync({ commit }) {setTimeout(() => {commit('increment')}, 1000)},// 带参数的形式incrementByAsync({ commit }, payload) {return new Promise((resolve) => {setTimeout(() => {commit('increment')resolve()}, payload.delay)})},// 组合多个actionactionA({ commit }) {return new Promise((resolve) => {setTimeout(() => {commit('someMutation')resolve()}, 1000)})},actionB({ dispatch, commit }) {return dispatch('actionA').then(() => {commit('someOtherMutation')})}}
})
分发 Actions

方法1:直接分发

methods: {increment() {this.$store.dispatch('incrementAsync')},addLater() {// 带参数this.$store.dispatch('incrementByAsync', { delay: 2000 })// 对象风格this.$store.dispatch({type: 'incrementByAsync',delay: 2000})// 处理Promisethis.$store.dispatch('actionB').then(() => {console.log('Action completed')})}
}

方法2:使用 mapActions 辅助函数

import { mapActions } from 'vuex'export default {methods: {// 数组形式 - 同名映射...mapActions(['incrementAsync', 'incrementByAsync']),// 对象形式 - 可自定义名称...mapActions({add: 'incrementAsync',addLater: 'incrementByAsync'}),// 使用方法addFiveLater() {this.addLater({ delay: 5000 }).then(() => console.log('Done!'))}}
}

5. Modules - 模块化

当应用变得复杂时,Store 对象可能变得臃肿。Vuex 允许我们将 store 分割成模块(module)。

const moduleA = {namespaced: true, // 启用命名空间state: { count: 0 },mutations: {increment(state) {state.count++}},getters: {doubleCount(state) {return state.count * 2}}
}const moduleB = {namespaced: true,state: { list: [] },actions: {fetchList({ commit }) {// 获取数据...}}
}const store = new Vuex.Store({modules: {a: moduleA,b: moduleB}
})
访问模块内容
// 访问模块 state
this.$store.state.a.count // -> moduleA 的 state
this.$store.state.b.list  // -> moduleB 的 state// 提交模块 mutation
this.$store.commit('a/increment')// 分发模块 action
this.$store.dispatch('b/fetchList')// 使用模块 getter
this.$store.getters['a/doubleCount']
使用辅助函数
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'export default {computed: {// 模块 state...mapState('a', ['count']),...mapState('b', ['list']),// 模块 getters...mapGetters('a', ['doubleCount'])},methods: {// 模块 mutations...mapMutations('a', ['increment']),// 模块 actions...mapActions('b', ['fetchList'])}
}
模块局部状态

在模块内部的 mutation 和 getter 中,接收的第一个参数是模块的局部状态对象:

const moduleA = {state: { count: 0 },mutations: {increment(state) {// state 是模块的局部状态state.count++}},getters: {doubleCount(state) {return state.count * 2},// 可以访问根节点状态sumWithRootCount(state, getters, rootState) {return state.count + rootState.count}},actions: {// 在action中可以通过 context.rootState 访问根状态incrementIfOdd({ state, commit, rootState }) {if ((state.count + rootState.count) % 2 === 1) {commit('increment')}}}
}

五、实际项目应用示例

1. 用户认证模块示例

// store/modules/auth.js
const state = {user: null,token: localStorage.getItem('token') || '',status: '' // 'loading', 'success', 'error'
}const getters = {isAuthenticated: state => !!state.token,authStatus: state => state.status,currentUser: state => state.user
}const mutations = {AUTH_REQUEST(state) {state.status = 'loading'},AUTH_SUCCESS(state, { token, user }) {state.status = 'success'state.token = tokenstate.user = userlocalStorage.setItem('token', token)},AUTH_ERROR(state) {state.status = 'error'localStorage.removeItem('token')},LOGOUT(state) {state.user = nullstate.token = ''localStorage.removeItem('token')}
}const actions = {login({ commit }, userData) {return new Promise((resolve, reject) => {commit('AUTH_REQUEST')axios.post('/api/auth/login', userData).then(res => {const { token, user } = res.datacommit('AUTH_SUCCESS', { token, user })resolve(res)}).catch(err => {commit('AUTH_ERROR')localStorage.removeItem('token')reject(err)})})},logout({ commit }) {return new Promise(resolve => {commit('LOGOUT')resolve()})}
}export default {namespaced: true,state,getters,mutations,actions
}

2. 在组件中使用

写文章-CSDN创作中心

<template><div><div v-if="!isAuthenticated"><button @click="login">登录</button></div><div v-else>欢迎, {{ currentUser.name }}!<button @click="logout">退出</button></div></div>
</template><script>
import { mapGetters, mapActions } from 'vuex'export default {computed: {...mapGetters('auth', ['isAuthenticated', 'currentUser'])},methods: {...mapActions('auth', ['login', 'logout']),login() {const userData = { username: 'test', password: '123456' }this.login(userData).then(() => {this.$router.push('/dashboard')}).catch(error => {console.error('登录失败:', error)})}}
}</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93682.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93682.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/93682.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pytorch 数据预处理,加载,训练,可视化流程

流程定义自定义数据集类定义训练和验证的数据增强定义模型、损失函数和优化器训练循环&#xff0c;包括验证训练可视化整个流程模型评估高级功能扩展混合精度训练​分布式训练​{:width“50%” height“50%”} 定义自定义数据集类 # #1. 自定义数据集类 # class CustomImageD…

Prompt工程:OCR+LLM文档处理的精准制导系统

在PDF OCR与大模型结合的实际应用中&#xff0c;很多团队会发现一个现象&#xff1a;同样的OCR文本&#xff0c;不同的Prompt设计会产生截然不同的提取效果。有时候准确率能达到95%&#xff0c;有时候却只有60%。这背后的关键就在于Prompt工程的精细化程度。 &#x1f3af; 为什…

RecSys:粗排模型和精排特征体系

粗排 在推荐系统链路中&#xff0c;排序阶段至关重要&#xff0c;通常分为召回、粗排和精排三个环节。粗排作为精排前的预处理阶段&#xff0c;需要在效果和性能之间取得平衡。 双塔模型 后期融合&#xff1a;把用户、物品特征分别输入不同的神经网络&#xff0c;不对用户、…

spring声明式事务,finally 中return对事务回滚的影响

finally 块中使用 return 是一个常见的编程错误&#xff0c;它会&#xff1a; 跳过正常的事务提交流程。吞掉异常&#xff0c;使错误处理失效 导致不可预测的事务行为Java 中 finally 和 return 的执行机制&#xff1a;1. finally 块的基本特性 在 Java 中&#xff0c;finally …

WPF 打印报告图片大小的自适应(含完整示例与详解)

目标&#xff1a;在 FlowDocument 报告里&#xff0c;根据 1~6 张图片的数量&#xff0c; 自动选择 2 行 3 列 的最佳布局&#xff1b;在只有 1、2、4 张时保持“占满感”&#xff0c;打印清晰且不变形。规则一览&#xff1a;1 张 → 占满 23&#xff08;大图居中&#xff09;…

【AI大模型前沿】百度飞桨PaddleOCR 3.0开源发布,支持多语言、手写体识别,赋能智能文档处理

系列篇章&#x1f4a5; No.文章1【AI大模型前沿】深度剖析瑞智病理大模型 RuiPath&#xff1a;如何革新癌症病理诊断技术2【AI大模型前沿】清华大学 CLAMP-3&#xff1a;多模态技术引领音乐检索新潮流3【AI大模型前沿】浙大携手阿里推出HealthGPT&#xff1a;医学视觉语言大模…

迅为RK3588开发板Android12 制作使用系统签名

在 Android 源码 build/make/target/product/security/下存放着签名文件&#xff0c;如下所示&#xff1a;将北京迅为提供的 keytool 工具拷贝到 ubuntu 中&#xff0c;然后将 Android11 或 Android12 源码build/make/target/product/security/下的 platform.pk8 platform.x509…

Day08 Go语言学习

1.安装Go和Goland 2.新建demo项目实践语法并使用git实践版本控制操作 2.1 Goland配置 路径**&#xff1a;** GOPATH workspace GOROOT golang 文件夹&#xff1a; bin 编译后的可执行文件 pkg 编译后的包文件 src 源文件 遇到问题1&#xff1a;运行 ‘go build awesomeProject…

Linux-文件创建拷贝删除剪切

文章目录Linux文件相关命令ls通配符含义touch 创建文件命令示例cp 拷贝文件rm 删除文件mv剪切文件Linux文件相关命令 ls ls是英文单词list的简写&#xff0c;其功能为列出目录的内容&#xff0c;是用户最常用的命令之一&#xff0c;它类似于DOS下的dir命令。 Linux文件或者目…

RabbitMQ:交换机(Exchange)

目录一、概述二、Direct Exchange &#xff08;直连型交换机&#xff09;三、Fanout Exchange&#xff08;扇型交换机&#xff09;四、Topic Exchange&#xff08;主题交换机&#xff09;五、Header Exchange&#xff08;头交换机&#xff09;六、Default Exchange&#xff08;…

【实时Linux实战系列】基于实时Linux的物联网系统设计

随着物联网&#xff08;IoT&#xff09;技术的飞速发展&#xff0c;越来越多的设备被连接到互联网&#xff0c;形成了一个庞大而复杂的网络。这些设备从简单的传感器到复杂的工业控制系统&#xff0c;都在实时地产生和交换数据。实时Linux作为一种强大的操作系统&#xff0c;为…

第五天~提取Arxml中描述信息New_CanCluster--Expert

🔍 ARXML描述信息提取:挖掘汽车电子设计的"知识宝藏" 在AUTOSAR工程中,描述信息如同埋藏在ARXML文件中的金矿,而New_CanCluster--Expert正是打开这座宝藏的密钥。本文将带您深度探索ARXML描述信息的提取艺术,解锁汽车电子设计的核心知识资产! 💎 为什么描述…

开源 C++ QT Widget 开发(一)工程文件结构

文章的目的为了记录使用C 进行QT Widget 开发学习的经历。临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 C QT Widget 开发&#xff08;一&#xff09;工程文件结构-CSDN博客 开源 C…

手写C++ string类实现详解

类定义cppnamespace ym {class string {private:char* _str; // 字符串数据size_t _size; // 当前字符串长度size_t _capacity; // 当前分配的内存容量static const size_t npos -1; // 特殊值&#xff0c;表示最大可能位置public:// 构造函数和析构函数string(…

C++信息学奥赛一本通-第一部分-基础一-第3章-第2节

C信息学奥赛一本通-第一部分-基础一-第3章-第2节 2057 星期几 #include <iostream>using namespace std;int main() {int day; cin >> day;switch (day) {case 1:cout << "Monday";break;case 2:cout << "Tuesday";break;case 3:c…

【leetcode 3】最长连续序列 (Longest Consecutive Sequence) - 解题思路 + Golang实现

最长连续序列 (Longest Consecutive Sequence) - LeetCode 题解 题目描述 给定一个未排序的整数数组 nums&#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。要求设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#x…

矿物分类系统开发笔记(一):数据预处理

目录 一、数据基础与预处理目标 二、具体预处理步骤及代码解析 2.1 数据加载与初步清洗 2.2 标签编码 2.3 缺失值处理 &#xff08;1&#xff09;删除含缺失值的样本 &#xff08;2&#xff09;按类别均值填充 &#xff08;3&#xff09;按类别中位数填充 &#xff08;…

《UE5_C++多人TPS完整教程》学习笔记43 ——《P44 奔跑混合空间(Running Blending Space)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P44 奔跑混合空间&#xff08;Running Blending Space&#xff09;》 的学习笔记&#xff0c;该系列教学视频为计算机工程师、程序员、游戏开发者、作家&#xff08;Engineer, Programmer, Game Developer, Author&…

TensorRT-LLM.V1.1.0rc1:Dockerfile.multi文件解读

一、TensorRT-LLM有三种安装方式&#xff0c;从简单到难 1.NGC上的预构建发布容器进行部署,见《tensorrt-llm0.20.0离线部署DeepSeek-R1-Distill-Qwen-32B》。 2.通过pip进行部署。 3.从源头构建再部署&#xff0c;《TensorRT-LLM.V1.1.0rc0:在无 GitHub 访问权限的服务器上编…

UniApp 实现pdf上传和预览

一、上传1、html<template><button click"takeFile">pdf上传</button> </template>2、JStakeFile() {// #ifdef H5// H5端使用input方式选择文件const input document.createElement(input);input.type file;input.accept .pdf;input.onc…