项目结构
在 store 文件夹下新建 user.js 和 cart.js 作为子模块:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | const static = () => ({
 })
 
 const getters = {
 
 }
 
 const mutations = {
 
 }
 
 const actions = {
 
 }
 
 export default {
 namespaced: true,
 state,
 getters,
 mutations,
 actions
 }
 
 | 
然后在 index.js 中引入:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | import { createStore } from 'vuex'import user from './modules/user'
 import cart from "./modules/cart";
 
 export default createStore({
 modules: {
 user,
 cart
 }
 })
 
 | 
在组件中使用
state
state 保存着全局的状态,这些状态是具有响应性的,应放在 computed 属性中。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | import {useStore, mapState} from 'vuex';import {computed} from "vue";
 
 setup() {
 const store = useStore();
 
 
 const username = computed(() => store.state.user.username);
 const age = computed(() => store.state.user.age);
 
 
 const stateFns = mapState('user', ['username', 'age']);
 const State = {};
 Object.keys(stateFns).forEach(fn_key => {
 const fn = stateFns[fn_key].bind({$store:store});
 State[fn_key] = computed(fn);
 });
 
 return {
 username,
 age,
 ...State
 }
 }
 
 | 
这里使用 bind({$store:store}) 是因为我们需要将通过 useStore 初始化的 store 与全局 $store 绑定,才可以访问到仓库中的内容。
getters
getters 的作用是对 state 中的数据进行一系列的计算,然后将结果返回。
getters 中的属性也应放在 computed 中。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | import {useStore, mapGetters} from 'vuex';import {computed} from "vue";
 
 setup() {
 const store = useStore();
 
 
 const username = computed(() => store.getters['user/getUsername']);
 const age = computed(() => store.getters['user/getAge']);
 
 
 const getterFns = mapGetters('user', ['getUsername', 'getAge']);
 const Getter = {};
 Object.keys(getterFns).forEach(fn_key => {
 const fn = getterFns[fn_key].bind({$store:store});
 Getter[fn_key] = computed(fn);
 });
 
 return {
 username,
 age,
 ...Getter
 }
 }
 
 | 
mutations
mutations 的作用是更改 state 的属性值,但是它必须是 同步的。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | import {useStore, mapMutations} from 'vuex';
 setup() {
 const store = useStore();
 
 
 function changeState() {
 store.commit('user/changeName', 'Bob');
 store.commit('user/changeAge', 22);
 }
 
 
 const mutationFns = mapMutations(['changeAge', "changeName"]);
 const Mutation = {};
 Object.keys(mutationFns).forEach(fn_key => {
 Mutation[fn_key] = mutationFns[fn_key].bind({$store:store});
 });
 const {changeName, changeAge} = Mutation;
 
 function changeState() {
 changeName('Bob');
 changeAge(23);
 }
 
 return {
 changeState
 }
 }
 
 | 
actions
可以在 actions 中提交 mutations,actions 支持异步。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | import {useStore, mapActions} from 'vuex';
 setup() {
 const store = useStore();
 
 
 function changeState() {
 store.dispatch('user/changeNameAsync', 'xxx');
 store.dispatch('user/changeAgeAsync', 'xxx');
 }
 
 
 const actionFns = mapActions('user', ['changeNameAsync', 'changeAgeAsync']);
 const Actions = {}
 Object.keys(actionFns).forEach(fn_key => {
 Actions[fn_key] = actionFns[fn_key].bind({$store:store});
 });
 
 const {changeNameAsync, changeAgeAsync} = Actions;
 
 function changeState() {
 changeNameAsync('xxx');
 changeAgeAsync(23);
 }
 
 | 
为什么 state 必须放在计算属性中?
如果我们将 state 中的属性放在 data 中:
| 12
 3
 4
 5
 
 | data() {return {
 username: this.$store.state.username
 }
 }
 
 | 
由于 data 只在 created 之前初始化一次,那么当通过提交 mutations 的方式修改 state 中的数据后,data 不会再次执行 this.$store.state.username,因此 username 的值也不会改变。
那为什么放在 computed 中就可以响应呢?因为 computed 属性通过依赖计算求值。
| 12
 3
 4
 5
 
 | computed: {name() {
 return this.$store.state.username;
 }
 }
 
 | 
也就是说,name 依赖于 this.$store.state.username,那么当 state 中的 username 发生改变后,computed 会重新获取它的值。