项目结构
在 store 文件夹下新建 user.js 和 cart.js 作为子模块:
1 2 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 中引入:
1 2 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 属性中。
1 2 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 中。
1 2 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 的属性值,但是它必须是 同步的。
1 2 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 支持异步。
1 2 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 中:
1 2 3 4 5
| data() { return { username: this.$store.state.username } }
|
由于 data 只在 created 之前初始化一次,那么当通过提交 mutations 的方式修改 state 中的数据后,data 不会再次执行 this.$store.state.username
,因此 username 的值也不会改变。
那为什么放在 computed 中就可以响应呢?因为 computed 属性通过依赖计算求值。
1 2 3 4 5
| computed: { name() { return this.$store.state.username; } }
|
也就是说,name 依赖于 this.$store.state.username,那么当 state 中的 username 发生改变后,computed 会重新获取它的值。