小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
Vuex中文文档:vuex.vuejs.org/zh/guide/
home页面:负责增加数据

about页面:负责减少数据

基础目录结构:默认Vuex代码写在index中,modules模块化代码则放在Addition.js与Subition.js中;state、mutations、actions、getters均有两种调用方式

注:两种调用方式分别使用在 Addition.vue 与 Subition.vue 中
export default createStore({
// State提供唯一的公共数据源,所有共享的数据都要统一放到Store的State中进行存储
state: {
// 组件里第一种访问State数据的方式:
// this.$store.state.全局数据名称;
count: 0 // this.$store.state.count;简写:$store.state.count
// 第二种访问State数据的方式:
// 在需要用到state数据的页面引入:import { mapState } from 'vuex'
// 将当前组件需要的全局数据,映射为当前组件的computed计算属性
// ...表示展开运算符,把当前全局数据映射为计算属性
// ...mapState(['count','更多数据']) ;指定需要引入这个页面的state数据
},
})
复制代码第一种方式在Addition页面使用

第二种方式在Subition页面使用
引入mapState

在computed里展开映射为计算属性

在页面中使用

export default createStore({
//Mutation用于变更Store中的数据,且只有mutation能够修改state数据
//Vuex的数据只能通过mutation变更,不可以直接操作Store中的数据
//用这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
//但是mutation不能异步操作
mutations: {
//mutation里的函数第一个参数默认都是state,这个state表示当前的数据
countAdd(state){
state.count++;
},
//使用参数进行相加
countAdds(state,step){
state.count+=step;
},
//第二种使用mutationd的方式;使用mapMutations导入使用mutations方法
countSub(state){
state.count--;
},
//使用参数进行相加
countSubs(state,step){
state.count -= step;
}
},
})
复制代码第一种调用方式


第二种
引入mapMutations

映射进methods

调用


export default createStore({
//ACtions提供异步操作
//如果要使用异步操作,就得在actions里进行,
//但是action还是得通过,触发mutation的方法简介变更数据
actions: {
//在actions中不能修改state的数据
countAddActions(context){ // context为默认参数
setTimeout( () => {
context.commit('countAdd') //调用mutations方法
},1000)
},
countAddsActions(context,step){
setTimeout( () => {
context.commit('countAdds',step)
},1000)
},
//第二种使用actions方法;使用mapActions导入使用actions方法
countSubActions(context){
setTimeout( () => {
context.commit('countSub')
},1000)
},
countSubsActions(context,step){
setTimeout( () => {
context.commit('countSubs',step)
},1000)
},
},
})
复制代码第一种方法


第二种方法

引入

映射

使用

注:除了mutations使用mapMutations映射进methods调用mutations方法除外的其他调用方法名都可设置为一样的。
export default createStore({
//Getter用于对Store中的数据进行加工处理,形成新的数据;类似vue的计算属性
//store中数据发生变化,getter的数据也会发生变化
getters: {
// 调用方法;this.$store.getters.方法名称;this.$store.getters.showCount
showCount(state){
return '当前最新的数据是【' + state.count + '】'
}
},
})
复制代码第一种方法

第二种
引入

映射

使用

//由于Vuex使用单—状态树,应用的所有状态会集中到一个比较大的对象。
//Vuex允许将store分割成模块(module)。
//每个模块拥有自己的state、mutation、action、getter、module,
//甚至是嵌套子模块----从上至下进行同样方式的分割。
// 引入模块js
import Addition from './Addition.js'
import Subition from './Subition.js'
export default createStore({
//使用这两个模块
modules: {
Addition,
Subition
}
)}
复制代码使用modules调用vuex与不使用时的区别:
state
// 模块内调用
state.属性名
// 跨模块调用
rootState.模块名.属性名
复制代码getters
// 模块内调用
getters.属性名
// 跨模块调用
rootGetters.模块名.属性名
复制代码mutation
// 模块内调用
commit('模块内方法名')
// 跨模块调用
commit('模块名/方法名')
复制代码action
// 模块内调用
dispatch('模块内方法名')
// 跨模块调用
dispatch('模块名/方法名')
复制代码示例:新建以下两个文件;并将原本index.js页面的内容分别移入Addition.js与Subition.js文件内

Addition.js页面;namespaced: true;设置命名空间,使其他页面可引入使用这个模块

Subition.js页面

Addition.vue;使用模块方法与数据都需要指定

Subition.vue;相应的map也得指定模块

映射方法后;正常调用

添加数据效果:因为使用的是各自页面的数据,所以展示数据相反

减少数据效果

就得使用跨模块调用:
注:先好好理解并消化上面的五种核心;之后的内容因为使用了跨模块调用,稍微有点复杂,所以将代码重新写了一遍。
修改后的 index.js 页面内容
import { createStore } from 'vuex'
import Addition from './Addition.js'
import Subition from './Subition.js'
//这里以counts与msg做例子;其中counts使用rootState进行修改
//msg以设置{root:true}属性来调用mutations修改
export default createStore({
state: {
// counts 使用跨模块使用 state
counts: 0,
// 跨模块调用 mutations
msg: 0
},
mutations: {
// 正常调用,使用传多参数的形式进行判断是相加还是相减以及增加或减少多少
// payload.status: 判断相加还是相减
// payload.num: 相加减的值
increment(state, payload) {
// 判断是否相加
if (payload.status == 'add') {
// 进行相加
state.counts = state.counts += payload.num
// 判断是否相减
} else if (payload.status == 'sub') {
// 相减
state.counts = state.counts -= payload.num
} else {
// 参数传错时
alert('想啥呢?参数只能是 add 或 sub ' + payload.num + payload.status)
}
}
},
actions: {
// 异步调用
incrementActions(context, num, status) {
setTimeout(() => {
context.commit('increment', num, status)
}, 1000)
}
},
//导入模块
modules: {
Addition,
Subition
}
})
复制代码Addition.vue页面:
template组件内容

不异步调用

异步调用

Addition.js页面
AdditionCount 的修改

跨模块修改 counts 与 msg

注:跨模块调用只能用作在 actions 里,不能在mutations里使用(网上搜了一堆教程没有一个指明,害我调了几天的bug)
Subition.vue(省略,可下载源码查看)
一模一样的代码,只是调用方式改变了而已
Vuex官网建议我们给mutations的方法命名为常量:

新建个mutations-type文件将使用的方法在这里声明const:

将所有Vuex页面的mutations都命名到这

//命名并导出
export const 常量名 = 方法名
//在需要使用的页面引入:
import {常量名} from './mutations-type'
// index.js使用方法:
[常量名] (state,payload) {
state.count += payload
}
// index.vue使用:
方法名(){
this$store.commit('模块名/' + 常量名, 参数)
}
//map方式引入:
...mapMutations('模块名',[常量名])
//map引入后调用:
方法名() {
this[常量名](参数)
}
复制代码index.js:


Addition.js:



Addition.vue:


Subition.vue:



代码过于复杂只看图示可能看不明白(ps:我自己也看不明白)
建议直接下载源代码查看
总结
在 Vuex中说白了,任何的操作都是围绕state来进行的, Vuex是状态管理器,作用就是管理state 中的状态,其他提供的所有功能Getter、Mutation、Action、Modules都是为了能够更好的管理state,而之所以设计成期望通过Mutation改变状态,是因为我们期望所有状态的变化都是有迹可循的!

import { createStore } from "vuex";
export default createStore({
//State提供唯一的公共数据源,所有共享的数据都要统一放到
//Store的State中进行存储
state: {
//组件里第一种访问State数据的方式:
// this.$store.state.全局数据名称;this.$store.state.count
count: 0
//第二种访问State数据的方式:
// import { mapState } from 'vuex';通过导入mapState函数
// 将当前组件需要的全局数据,映射为当前组件的computed计算属性
},
//Mutation用于变更Store中的数据,且只有mutation能够修改state数据
//Vuex的数据只能通过mutation变更,不可以直接操作Store中的数据
//用这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
//mutation不能异步操作
mutations: {
//mutation里的函数第一个参数都默认是state,这个state表示当前的数据
countAdd(state){
state.count++;
},
//使用参数进行相加
countAdds(state,step){
state.count+=step;
},
//第二种使用mutationd的方式;使用mapMutations导入使用mutations方法
countSub(state){
state.count--;
},
//使用参数进行相加
countSubs(state,step){
state.count -= step;
}
},
//ACtions提供异步操作
//如果要使用异步操作,就得在actions里进行,但是action还是得通过
//触发mutation的方法简介变更数据
actions: {
//在actions中不能修改state的数据
countAddActions(context){
setTimeout( () => {
context.commit('countAdd')
},1000)
},
countAddsActions(context,step){
setTimeout( () => {
context.commit('countAdds',step)
},1000)
},
//第二种使用actions方法;使用mapActions导入使用actions方法
countSubActions(context){
setTimeout( () => {
context.commit('countSub')
},1000)
},
countSubsActions(context,step){
setTimeout( () => {
context.commit('countSubs',step)
},1000)
},
},
//Getter用于对Store中的数据进行加工处理,形成新的数据;类似vue的计算属性
//store中数据发生变化,getter的数据也会发生变化
getters: {
// 调用方法;this.$store.getters.方法名称;this.$store.getters.showCount
showCount(state){
return '当前最新的数据是【' + state.count + '】'
}
},
modules: {}
});
复制代码<template>
<div>
<!-- 也可以简写为$store.state.count -->
<h3>当前最新的count值为:{{ this.$store.state.count }}</h3>
<button @click="countAdd">1++</button>
<button @click="countAdds">n++</button>
<button @click="countAddActions">1++Action</button>
<button @click="countAddsActions">n++Action</button>
<!-- 使用计算属性显示count的值 -->
<p>{{ $store.getters.showCount }}</p>
</div>
</template>
<script>
export default {
data(){
return{
};
},
methods: {
countAdd(){
/*
不能这样写,如果state里的数据被修改了,并出现了报错
那么这时候去查错,就只能一个一个文件的去翻找是那个文件出现了错误
但如果使用mutations进行修改数据,那么数据出错时就只需要找它就行了
this.$store.state.count++;
*/
//使用mutations方法调用;this.$store.commit("方法名")
this.$store.commit('countAdd')
},
//以传参的方式进行添加
countAdds(){
//传入一个参数3,实现每次加3;this.$store.commit("方法名", 参数)
this.$store.commit('countAdds', 3)
},
//使用异步操作;this.$store.dispatch('方法名')
countAddActions(){
this.$store.dispatch('countAddActions')
},
//异步传参;this.$store.dispatch('方法名', 参数)
countAddsActions(){
this.$store.dispatch('countAddsActions', 5)
}
}
}
</script>
复制代码<template>
<div>
<!-- 引用mapState后,只需要直接输入数据名就可引用了 -->
<h3>当前最新的count值为:{{ count }}</h3>
<button @click="btn1">1--</button>
<button @click="btn2">n--</button>
<button @click="countSubActions">1--Action</button>
<button @click="countSubsActions">n--Action</button>
<!-- 使用计算属性显示count的值 -->
<p>{{ $store.getters.showCount }}</p>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
export default {
data(){
return{
}
},
computed: {
//...表示展开运算符,把当前全局数据映射为计算属性
...mapState(['count']),
//第二种引入Getters的方法
...mapGetters(['showCount'])
},
methods: {
//把mutations映射到methods中
...mapMutations(['countSub','countSubs']),
...mapActions(['countSubActions','countSubsActions']),
/*
特别注意!!!如果是使用mapMutations方法引入的mutations方法
其mutations里定义的方法名和methods定义的方法名不能相同!
因为已经将mutations映射到methods中了,调用mutations的方法
等同调用methods的方法;因为两个相同命名的方法被递归调用从而引发了报错
Maximum call stack size exceeded
*/
btn1(){
//因为已经映射到methods中,从而可以直接调用方法
this.countSub()
},
btn2(){
this.countSubs(3)
},
//使用异步操作
countSubActions(){
this.$store.dispatch('countSubActions')
},
//异步传参
countSubsActions(){
this.$store.dispatch('countSubsActions', 5)
}
}
}
</script>
复制代码未使用模块化的下载地址:📎vuex.zip
使用模块化并且mutations常量化命名的下载地址:📎vuex.zip
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。