Vuex
Vuex
是vue.js
的状态管理模式,听着一脸懵逼,通俗一点来事,Vuex
就是一个仓库,公众的状态我们把它放进去。
安装
输入命令vue add vuex
等候安装完成后会在src
文件夹下出现store
文件,store
文件下的index.js
为vuex
的主文件。
vue add vuex
核心概念
Vuex
是单向数据流的设计模式,其有五大核心概念State、Getter、Mutation、Action和Module
,在本篇博客中将记录这五大核心概念的使用和作用。
State
State
是用来存放数据的,通常将全局数据将保存在这里。
// store/index.js
export default new Vuex.Store({
state: {
msg: 'hello world'
}
// ...
})
<template>
<div id="app">{{msg}}</div>
</template>
<script>
export default {
data() {
return {
msg: this.$store.state.msg
};
}
};
</script>
在vue
组件中我们可以通过this.$store.state
来获取vuex
下的state
状态。
辅助函数
通过辅助函数,我们可以快速的获取到State
中存放的数据。
<template>
<div id="app">{{msg}}</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed:mapState({
msg: item => item.msg
})
};
</script>
对于大量数据的时候设置使得代码臃肿,我们可以使用...
展开运算符。
<template>
<div id="app">{{msg}}{{msg2}}</div>
</template>
<script>
import { mapState } from "vuex";
export default {
computed: {
...mapState(["msg","msg2"])
}
};
</script>
Getter
有些时候我们需要从store
中的state
中返回特定的模板或者计算,这个时候我们就需要用到Getter
<template>
<div id="app">{{print}}</div>
</template>
<script>
export default {
data(){
return {
print: this.$store.getters.print
}
}
};
</script>
辅助函数
辅助函数的用法都是一致的,但是在实际开发流程中,模块可能是不能人员开发的,所以我们可以重命名避免与别人的模块命名冲突。
<template>
<div id="app">{{userinfo}}</div>
</template>
<script>
import { mapState, mapGetters } from "vuex";
export default {
computed: {
...mapGetters({
userinfo: "print"
})
}
};
</script>
Mutation
Mutation
使用来修改state
中的数据,不支持异步修改。
// vue
<template>
<div id="app">{{userinfo}}<button @click="setage">修改</button></div>
</template>
<script>
import { mapState, mapGetters, mapMutations } from "vuex";
export default {
methods:{
...mapMutations(['changeAge']),
setage(){
this.changeAge([20])
}
},
computed: {
...mapGetters({
userinfo: "print"
})
}
};
</script>
// store/index/js
export default new Vuex.Store({
state: {
msg: 'hello world',
name: 'rabbit',
age: 18
},
getters: {
print(state) {
return `姓名:${state.name} 年龄:${state.age}`
}
},
mutations: {
changeAge(state, payload) {
state.age = payload[0]
}
},
actions: {
},
modules: {
}
})
Action
Action
和 Mutation
都是修改state
中的数据,唯一的区别就是Action
支持异步调用Mutation
来修改。
export default new Vuex.Store({
state: {
msg: 'hello world',
name: 'rabbit',
age: 18
},
getters: {
print(state) {
return `姓名:${state.name} 年龄:${state.age}`
}
},
mutations: {
changeAge(state, payload) {
state.age = payload[0]
}
},
actions: {
asychangeAge({ commit }, payload) {
return new Promise((resolve, reject) => {
setInterval(() => {
commit('changeAge', payload);
resolve();
}, 3000)
})
}
},
modules: {
}
})
<template>
<div id="app">{{userinfo}}<button @click="setage">修改</button></div>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
methods:{
...mapActions(['asychangeAge']),
setage(){
this.asychangeAge([18]).then(() => {
console.log('修改完成')
})
}
},
computed: {
...mapGetters({
userinfo: "print"
})
}
};
</script>
Module
我们将store
分割成模块,每个模块拥有自己的 state、mutation、action、getter
、甚至是嵌套子模块,这样的话就解决了多人写作开发中同名数据发生冲突导致被修改。
export default new Vuex.Store({
// ......
modules: {
moduleA: {
namespaced: true,
state: {
name: 'moduleA'
},
getters: {},
mutations: {
changeName(state, payload) {
console.log(payload)
state.name = payload
}
},
actions: {
asychangeName({ commit }, payload) {
commit('changeName', payload);
}
}
},
moduleB: {
namespaced: true,
state: {
name: 'moduleB'
},
getters: {},
mutations: {
changeName(state, payload) {
console.log(payload)
state.name = payload
}
},
actions: {
asychangeName({ commit }, payload) {
commit('changeName', payload);
}
}
},
}
})
在模块内我们写有两个独立的模块moduleA
和moduleB
,每个模块也有着独立的五大核心概念。
<template>
<div id="app">
{{moduleA}}
<br />
{{moduleB}}
<br />
<button @click="setage">修改</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
methods: {
// 收集并重命名模块A中的Action
...mapActions("moduleA", {
asychangeModuleA: "asychangeName"
}),
// 收集并重命名模块B中的Action
...mapActions("moduleB", {
asychangeModuleB: "asychangeName"
}),
setage() {
// 修改模块A中的数据
this.asychangeModuleA("This is the value of moduleA I modified").then(() => {
console.log("修改moduleA成功");
});
// 修改模块B中的数据
this.asychangeModuleB("This is the value of moduleB I modified").then(() => {
console.log("修改moduleB成功");
});
}
},
computed: {
// 收集并重命名模块A中的State
...mapState("moduleA", {
moduleA: state => state.name
}),
// 收集并重命名模块B中的State
...mapState("moduleB", {
moduleB: state => state.name
})
}
};
</script>
严格模式
Vuex
是一个单向数据流的模式,State
中数据想要发生改变,根据规范需要在Mutation
中去修改他,Action
决定Mutation
什么时候去执行,这就是一个单向数据流的模式。
开启严格模式,就必须通过Mutation
来进行修改数据,否则将抛出错误。
const store = new Vuex.Store({
// ...
strict: true
})
请不要再发布环境中使用严格模式,严格模式会深度检测不符合规范的State
更改,十分消耗性能,我们可以使用判断环境动态设置严格模式。
const store = new Vuex.Store({
// ...
strict: process.env.NODE_ENV !== 'production'
})