Vuex是转为vue应用程序开发的状态管理模式,采用集中式存储管理应用的所有组件的状态
//在脚手架的main.js文件中
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
Vue.use(Vuex)
//实例化Vuex
const store = new Vuex.store({
//在这里定义state/mutations/actions等,且均为对象形式
state:{
},
mutations:{
},
actions:{
}
})
new Vue({
render: h => h(App),
//注入Vuex
store
}).$mount('#app')
state是放置公共状态的属性
定义state
//main.js
const store = new Vuex.store({
//在这里定义state/mutations/actions等,且均为对象形式
state:{
num:0
}
})
//test.vue
//在组件中获取vuex的state状态数据 有两种方法
//1.通过$store(挂载到Vue中接收Vuex.store的常量名).state获取
//$store.state.num
//2.通过Vuex提供的辅助方法 mapState 获取
//import {mapState} from 'vuex',然后在computed属性中定义
<template>
<div>原始方法拿count:{
{
$store.state.num }}</div>//0
<div>用computed方法拿num:{
{
getNum }}</div>//0
<div>用辅助函数+computed方法拿num:{
{
num }}</div>//0
</template>
<script>
import {
mapState} from "vuex";
export default {
computed: {
...mapState(["num"]),
getNum(){
return this.$store.state.num
}
}
};
state数据的修改只能通过mutations,并且mutations必须是同步更新
//main.js
const store = new Vuex.store({
//在这里定义state/mutations/actions等,且均为对象形式
state:{
num:0
},
mutations:{
// 方法里参数 第一个参数是当前store的state属性
addNum(state){
state.num ++
},
//第二个参数是载荷 运输参数 调用mutaiions的时候 可以传递参数 传递载荷
numPlusVar(state,var){
state.num += var
}
})
//使用
//test.vue
//mutations修改vuex的state状态数据 有两种方法,类似于state
//1.通过$store.commit('方法名')方法获取
//2.通过Vuex提供的辅助方法 mapMutations获取
//import {mapMutations } from 'vuex',然后在methods属性中定义
//如果是带参的,则在方法后面传参即可
<template>
<div>{
{
num }}</div>//0
<button @click="numAdd1">用commit方法+1</button>
<button @click="numAddVar">用commit方法传参修改</button>
<button @click="addNum">用mapMutations方法+1</button>
<button @click="numPlusVar(100)">用mapMutations方法传参修改</button>
</template>
<script>
import {
mapState,mapMutations } from "vuex";
export default {
methods:{
//方法1
numAdd1(){
this.$store.commit('addNum')
},
numAddVar(){
this.$store.commit('numPlusVar',100)
},
//方法2 -- mapMutations 传入数组,定义函数
...mapMutations(['addNum','numPlusVar'])
},
computed: {
...mapState(["num"])
}
};
mutations是同步更新数据,actions则负责进行异步操作
//main.js
const store = new Vuex.store({
//在这里定义state/mutations/actions等,且均为对象形式
state:{
num:0
},
mutations:{
numPlusVar(state,var){
state.num += var
}
},
actions:{
// 获取异步的数据 第一个参数context表示当前的store的实例 可以通过 context.state 获取状态 也可以通过context.commit 来提交mutations, 也可以 context.diapatch调用其他的action
asyncAddNum(context,var){
setTimeout(function(){
// 一秒钟之后 去修改state中的num,带参
context.commit('numPlusVar', var)
}, 1000)
}
}
})
//使用
//有两种方式
//1.通过$store.dispatch('方法名')来使用
//2.通过辅助函数mapActions来使用
//import { mapActions } from 'vuex',然后在methods中定义
<template>
<div>{
{
num }}</div>//0
<button @click="asyncChange">用原始dispacth方法异步修改</button>
<button @click="asyncAddNum(100)">用mapActions方法异步修改</button>//一秒后+100
</template>
<script>
import {
mapState,mapActions } from "vuex";
export default {
computed: {
...mapState(["num"])
},
methods:{
//方法1
asyncChange(){
//一秒后+10
this.$store.dispatch('asyncAddNum',10)
},
//方法2
...mapActions(['asyncAddNum'])
}
除了state之外,有时我们还需要从state中派生出一些状态,这些状态是依赖state的,此时会用到getters
例如:state中有数组list:[0,1,2,3,4,5,6,7,8,9],但只想要其中大于3的数值,如果不用getters,那么就需要先获取再修改,而getter可以先处理数据,再通过返回值返回数据
//main.js
const store = new Vuex.store({
state:{
list:[0,1,2,3,4,5,6,7,8,9]
},
getters:{
// getters函数的第一个参数是 state
// 必须要有返回值
//采用es6的简写
listFilter:state => state.list.filter(item => item > 3)
}
})
//使用
//两种方法,类似于state
//1.通过$store.getters.函数名,或是在computed中定义
//2.通过辅助函数mapGetters
<template>
<div>原始方法{
{
$store.getters.listFilter }}</div>//[4,5,6,7,8,9]
<div>原始方法+computed{
{
filtedList }}</div>//[4,5,6,7,8,9]
<div>mapActions方法{
{
listFilter }}</div>//[4,5,6,7,8,9]
</template>
<script>
import {
mapActions } from "vuex";
export default {
computed: {
filtedList(){
//方法1
return this.$store.getters.listFilter
},
//方法2
...mapActions(['listFilter'])
},
</script>
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。简而言之:如果把所有的状态都放在state中,当项目变得越来越大的时候,Vuex会变得越来越难以维护,由此,又有了Vuex的模块化
原理:
假如: 有两个模块,user模块用来存储token,setting模块用来存储用户名username
//main.js
const store = new Vuex.Store({
modules: {
user: {
state: {
token: '12345'
}
},
setting: {
state: {
name: 'Thomas'
}
}
})
//在模块里面的state是全局vuex可用的,所以获取有两种方法
//1.通过$store.state.模块名称.模块中的state名称
//$store.state.user.token / $store.state.setting.name
//2.通过store中的根getters来定义
getters: {
token: state => state.user.token,
name: state => state.setting.name
}
//使用
<template>
<div>原始方法{
{
$store.state.user.token }}</div>//'12345'
<div>mapGetters方法{
{
token }}</div>//'12345'
<div>mapGetters方法{
{
name }}</div>//'Thomas'
</template>
<script>
import {
mapGetters } from "vuex";
export default {
computed: {
//方法2
...mapGetters(['token','name'])
},
</script>
默认情况下,module模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
简而言之:模块之间的 action、mutation 和 getter 其实并没有区分,都可以直接通过全局的方式调用
例如:
modules: {
user: {
state: {
token: '12345'
},
mutations:{
// 这里的state表示的是user的state
updateToken (state) {
state.token = '6789'
}
},
}
<template>
<div>{
{
$store.state.user.token }}</div>//'12345'
<button @click='updateToken'>修改token</button>
</template>
<script>
import {
mapMutations } from "vuex";
export default {
methods:{
...mapMutations(['updateToken'])//修改module中user的token
}
}
</script>
但是,如果我们想保证内部模块的高封闭性,我们可以采用nameSpaced:true
来进行设置
modules: {
user: {
nameSpaced:true,//命名空间
state: {
token: '12345'
},
mutations:{
// 这里的state表示的是user的state
updateToken (state) {
state.token = '6789'
}
},
}
//此时,组件中的 ...mapMutations(['updateToken'])将会失效
如果需要使用命名空间中的mutations
方法1:mapMutations带上模块名
...mapMutations(['user/updateToken']),
changeToken(){
this['user/updateToken']()
}
//template
<button @click='changeToken'>修改token</button>
方法2:使用辅助函数createNamespacedHelpers
来创建基于某个命名空间辅助函数
import {
createNamespacedHelpers } from 'vuex' //引入辅助函数
const {
mapMutations } = createNamespacedHelpers('user') // 拿到模块user,然后拿到user中的mutations
//相当于 const mapMutations = createNamespacedHelpers('user').mutations
export default {
methods:{
...mapMutations(['updateToken ']) //user中的mutations
}
}
<div>{
{
$store.state.user.token}}</div>
<button @click="changeToken">用createNamespacedHelpers来调用命名空间中的mutations</button>