vuex出现的原因:
由于状态零散地分布在许多组件和组件之间的交互中,大型应用复杂度也经常逐渐增长。为了解决这个问题,Vue 提供 vuex进行状态管理,负责组件间的通信。
vuex解决的问题:
1. 多个vue文件依赖同一个状态
2. 来自多个vue文件的事件变更同一个状态
vuex的基本使用方法:
State:在state中添加数据
{
state: {
name:'Tom',
age: 999
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
}
vue文件获取state的方法一:
直接使用$store.state.属性
<template>
<div>
<div>{{ $store.state.name }}</div>
<div>{{ $store.state.age }}</div>
</div>
</template>
vue文件获取state的方法二:
使用mapState映射state数据到computed中
<template>
<div>
<div>{{ name }}</div>
<div>{{ age }}</div>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: {
// 映射store到组件计算属性中,可直接使用
...mapState(['name', 'age'])
},
};
</script>
Mutation:
store中的状态不能直接进行操作,我们使用mutation对store中的状态进行修改,便于监听数据的变化。
store中的状态必须通过Mutation的方法来处理。
{
state: {
name:'Tom',
age: 999
},
getters: {
},
mutations: {
changeName(state, newName) {
state.name = newName;
}
},
actions: {
},
modules: {
}
}
vue文件使用mutation的方式一:
$store.commit()方式在methods方法中触发
<template>
<div>
{{ name }}
<button @click="getMutation">触发mutations 方式1</button>
</div>
</template>
import { mapState } from "vuex";
<script>
export default {
computed: {
// 映射store到组件计算属性中,可直接使用
...mapState(['name', 'age'])
},
methods: {
// 触发mutation中的方法
getMutation() {
this.$store.commit('changeName', 'mutation 冲浪')
},
}
}
<script>
vue文件使用mutation的方式二:
使用mapMutations映射mutation方法到methods中
<template>
<div>
{{ name }}
<button @click="changeName('mutation 浪啊')">触发mutation 方法2</button>
</div>
</template>
<script>
import { mapState, mapMutation } from "vuex";
export default {
computed: {
// 映射store到组件计算属性中,可直接使用
...mapState(['name', 'age'])
},
methods: {
// 映射mutation方法到组件methods中,可直接使用
...mapMutations(['changeName']),
}
}
<script>
Action:
Action和Mutation的区别: Action处理的是异步任务,异步任务必须通过Action触发Mutation方法改变状态,不能直接使用Mutation直接对异步任务进行修改。
在Action中定义异步方法来调用Mutation的方法:
{
state: {
name:'Tom',
age: 999
},
getters: {
},
mutations: {
/**
* @param {*} state 第一个参数 store中的状态(必须传递)
* @param {*} newName 第二个参数传入
*/
changeName(state, newName) {
state.name = newName;
}
},
actions: {
/**
*
* @param {*} context 上下文默认传递的参数
* @param {*} newName 自己传的参数
*/
// 定义一个异步的方法
changeNameAsync(context,newName) {
// 定时器模拟异步
setTimeout(() => {
// 调用mutations中的方法
context.commit('changeName', newName)
}, 2000)
}
},
modules: {
}
})
vue文件使用action的方式一:
this.$store.dispath()在methods方法中触发
<template>
<div>
{{ name }}
<button @click="getAction('action 冲浪')">action 方式1</button>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: {
// 映射store到组件计算属性中,可直接使用
...mapState(['name'])
},
methods: {
getAction(newName){
// dispath触发action中的方法
this.$store.dispath('changeNameAsync',newName)
}
}
}
<script>
vue文件使用action的方式二:
使用mapAction映射actions方法到methods中
<template>
<div>
{{ name }}
<button @click="changeNameAsync('action 浪啊')">action 方式2</button>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: {
// 映射store到组件计算属性中,可直接使用
...mapState(['name'])
},
methods: {
// 映射actions方法到组件methods中,可直接使用
...mapAction(['changeNameAsync'])
}
}
<script>
Getter:
Getter类似于计算属性,数据来源于Vuex中的State,Vuex中的数据需要简单包装处理由计算属性Getter来完成。
{
state: {
name:'Tom',
age: 999
},
getters: {
getterName(state) {
return state.age + 1;
}
},
mutations: {
/**
* @param {*} state 第一个参数 store中的状态(必须传递)
* @param {*} newName 第二个参数传入
*/
changeName(state, newName) {
state.name = newName;
}
},
actions: {
/**
* @param {*} context 上下文默认传递的参数
* @param {*} newName 自己传的参数
*/
// 定义一个异步的方法
changeNameAsync(context, newName) {
// 定时器模拟异步
setTimeout(() => {
// 调用mutations中的方法
context.commit('changeName', newName)
}, 2000)
}
},
modules: {
}
})
vue文件使用getter的方式一:
$store.getters.属性直接使用
<template>
<div>
{{ $store.getter.getterAge }}
</div>
</template>
vue文件使用getter的方式二:
使用mapGetters映射getter方法到computed中
<template>
<div>
{{ getterAge }}
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
computed: {
// 映射getter方法到组件计算属性中,可直接使用
...mapGetters(['getterAge'])
},
}
<script>
Module:
Vuex由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。Vuex允许Store分成不同模块,每个模块都拥有自己的state,getter,mutation,action
新建一个tag 模块
export default {
/**
* 开启模块的命名空间,确保不同部分的代码可以使用相同的名称而不产生冲突。
* @returns namespaced: true,
*/
namespaced: true, // ❤❤注意:第一种方式时,不写入,第二种方式,写入
state: () => ({
defaultTime: '2023-09-01'
}),
mutations: {
SET_DEFAULTTIME: (state, time) => {
state.defaultTime = time;
}
}
}
在store/index.js中引入,挂载在modules
import tag from './modules/tagName'
modules: {
tag
}
vue文件中使用方式一:
this.$store.state.tag.属性直接使用
<template>
<div>
{{ $store.state.tag.defaultTime }}
<button @click="$store.commit('SET_DEFAULTTIME','2000-20-20')">tag 方法1</button>
</div>
</template>
vue文件中使用方式二:
使用mapMutations映射mutation方法到methods中
<template>
<div>
<div>{{ defaultTime }}</div>
<button @click="SET_DEFAULTTIME('1000-10-10')">tag 方法2</button>
</div>
</template>
<script>
import { mapState, mapMutations } from "vuex";
export default {
computed: {
// mapState使用与之前不同,
// 第一个参数Modules挂载的模块名,
// 第二个参数tag模块中的属性名
...mapState('tag', ['defaultTime'])
},
methods: {
// mapMutations使用与之前不同,
// 第一个参数Modules挂载的模块名,
// 第二个参数tag模块中的方法名
...mapMutations('tag', ['SET_DEFAULTTIME']),
}
};
</script>