vuex概述
vuex是一个 vue 的状态管理工具( 状态就是数据 )。
vuex 是一个插件,可以帮我们管理 vue 通用的数据 (多组件共享的数据)
场景:
某个状态在很多个组件来使用
多个组件 共同维护 一份数据
……
优势:
共同维护一份数据,数据集中化管理
响应式变化
操作简洁 (vuex提供了一些辅助函数)
构建 vuex (多组件数据共享)环境
-
创建
shft + 鼠标右键 → 在此处打开Powershell窗口,输入
vue create 项目名
选择第三个,自定义创建项目
暂时 先勾Babel css linter
版本选 2
less
第三个
lint on save
第一个
n
- 运行
cd 项目名
yarn serve
写入一些组件,构建一个多组件数据共享)环境
-
创建一个空仓库
-
安装 vuex(vue2 装 3,vue3 装 4)(如果上面步骤勾选了 vuex 则不需要装包,会自动配好)
VSCode 终端中 输入
yarn add vuex@3
-
新建 vuex 模块文件
src 文件夹下 新建 store/index.js 专门存放 vuex 相关的核心代码
-
创建仓库
import Vue from 'vue' import Vuex from 'vuex' // 插件安装 Vue.use(Vuex) // 创建仓库(空仓库) const store = new Vuex.Store() //导出给main.js使用 export default store
main.js 挂载
import stroe from '@/store/index' new Vue( render: h => h(App), store ).$mount('#app')
(ps:获取stroe:this.$store)
-
核心概念 - state状态
仓库数据:
const store = new Vuex.Store({
state: {
title: 'hello'
}
})
使用仓库数据:
-
通过 store 直接访问
// 模板中 {{ $store.state.xxx }} // 组件逻辑中 this.$store.state.xxx // js 模块 store.state.xxx
-
通过辅助函数(简化)
mapState 是辅助函数,帮助我们把 store中的数据自动映射到 组件的计算属性中,该函数返回一个对象
import { mapState } from 'vuex' computed:{ ...mapState(['title']) } // 模板中可以直接使用 {{ title }}
核心概念 - mutations
vuex 同样遵循单向数据流,组件中不能直接修改仓库的数据,state数据的修改只能通过mutations
开启严格模式可以帮助初学者检测不规范的代码(默认不会报错),上线时需要关闭 (会消耗性能)
const store = new Vuex.Store({
strict:true,
})
mutations
store/index.js 文件中
const store = new Vuex.Store({
mutations:{
// 所有mutation函数,第一个参数,都是state
函数名 (state){
}
}
})
组件中
methods:{
函数名 (){
// 相当于调用mutations中相关函数
this.$store.commit('函数名')
}
}
mutations的带参数(如需多个参数,可以包装成一个对象传递)
组件中
methods:{
函数名 (){
this.$store.commit('',参数)
}
}
store/index.js 文件中
const store = new Vuex.Store({
mutations:{
函数名 (state,参数){
}
}
})
辅助函数:mapMutations
mapMutations 和mapState很像,它是把位于mutations中的方法提取了出来,映射到组件methods中
组件中
import { mapState,mapMutations } from 'vuex'
methods:{
...mapMutations(['仓库中对应的mapMutations函数名'])
}
使用时直接使用仓库中对应的函数名就行
相当于在methods自动添加的了一个函数:
methods:{
仓库中对应的mapMutations函数名 (参数){
this.$store.commit('仓库中对应的函数名', 参数)
}
}
核心概念 - actions
处理异步代码。说明:mutations必须是同步的((便于监测数据变化)记录调试)
注意:不能直接操作 state,操作 state,还是需要commit mutation
store/index.js 文件中
const store = new Vuex.Store({
actions:{
//context上下文(此处未分模块,可以当成 store仓库)
//context.commit(‘mutation名字',额外参数)
函数名 (context,参数){
//这里是setTimeout模拟异步,以后大部分场景是发请求
setTimeout(() =>{
context.commit('changeCount', 参数)
},1000)
}
}
})
组件中
// 调用 action
this.$store.dispatch('action 名字',参数)
辅助函数:mapActions
mapActions 是把位于 actions中的方法提取了出来,来,映射到组件methods中
组件中
import { mapState,mapMutations,mapActions } from 'vuex'
methods:{
...mapActions (['仓库中对应的actions函数名'])
}
使用时直接使用仓库中对应的函数名就行
相当于在methods自动添加的了一个函数:
methods:{
仓库中对应的actions函数名 (参数){
this.$store.dispatch('action 名字',参数)
}
}
核心概念 - getters
类似于计算属性
除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters
-
定义 getters
注意点:
- 形参第一个参数,就是state
- 必须有返回值,返回值就是getters的值
store/index.js 文件中
const store = new Vuex.Store({ getters:{ 函数名 (){ return } } })
访问 getters
-
通过 store 访问 getters
{{ $store.getters.函数名}}
-
通过辅助函数 mapGetters映射
组件中
import { mapState,mapMutations,mapActions,mapGetters } from 'vuex' // mapGetters 映射属性 所以应该写在计算属性里 computed: { ...mapGetters(['函数名']) }
核心概念-模块module(进阶语法)
由于vuex使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。(当项目变得越来越大的时候,Vuex会变得越来越难以维护)
模块拆分:
store/modules/xxx.js 文件下
const state = {}
const mutations = {}
const actions = {}
const getters = {}
export default{
state,
mutations,
actions,
getters
}
index.js
import xxx from './modules/xxx'
const store = new Vuex.Store({
modules:{
xxx
}
})
分模块后子模块的状态,还是会挂到根级别的state 中,属性名就是模块名
使用模块中的数据:
-
直接通过模块名访问
$store.state.模块名.xxx
-
通过 mapState 映射
-
默认根级别的映射 (模块引入时,是把模块的所有 state等 数据包成对象的方式添加,key为模块名)
computed: { ...mapState(['模块名']), }
-
子模块的映射
-
需要开启命名空间
子模块文件下
export default{ namespaced:true, state, mutations, actions, getters }
-
组件下
mapState('模块名',['xxx'])
-
-
使用模块中的 getters 中的数据:
模块文件中
const getters = {
// 分模块后,state指代子模块的state
xxx (state) {
return
}
}
-
直接通过模块名访问
$store.getters['模块名/xxx'] // 加中括号是因为有 / 的原因
-
通过 mapGetters 映射
需要开启命名空间
computed: { ...mapGetters('模块名',['xxx']) }
模块中mutation的调用语法:
注意:默认模块中的mutation和actions会被挂载到全局
需要开启命名空间,才会挂载到子模块。
-
直接通过 store 调用
this.$store.commit('模块名/xxx',额外参数)
-
通过 mapMutations 映射 子模块的映射 (需要开启命名空间)
methods { ... mapMutations('模块名',['xxx']) }
模块中 action 的调用语法:
const actions = {
xxx (context,newUserInfo){
// 调用mutation context上下文默认提交的就是自己模块的state和mutation
context.commit('xxx',传参)
// 不需要 模块名/xxx
}
}
注意:默认模块中的mutation和actions会被挂载到全局
需要开启**命名空间**,才会挂载到**子模块**。
-
直接通过 store 调用
this.$store.dispatch('模块名/xxx',额外参数)
-
通过 mapMutations 映射 子模块的映射 (需要开启命名空间)
methods { ...mapActions('模块名',['xxx']) }