vue经典的状态管理工具。
安装
// vue2
npm install vuex
// vue3
npm install vuex@next
使用
// Vue3
import { createStore } from 'vuex'
const store = createStore({})
app.use(store)
// vue2
import Vuex from 'vuex'
const store = new Vuex.Store({})
Vue.use(Vuex)
store的核心属性
state:状态值
getters: 从 store 中的 state 中派生出一些状态
mutation:更改状态的同步方法
action:与mutation类似,可以为异步方法,通过mutation更改状态,而不是直接更改。
modules:嵌套模块,同样可以包含这5个核心属性,用于大项目数据较大时使用。
定义核心属性
// type.ts export interface RootState { count: number } export interface AModuleState { a: number } export interface BModuleState { b: number } export interface State extends RootState { a: AModuleState b: BModuleState } // store.ts
export const key: InjectionKey<Store<State>> = Symbol() export const store = createStore<RootState>({ state: { count: 0 }, getters: { // 四个参数 double(state, getters, rootState, rootGetters) { console.log({ state, getters, rootState, rootGetters }) return state.count * 2 } }, mutations: { // 两个参数 increment(state, payload) { state.count++ } }, actions: { // 两个参数 increment( { dispatch, commit, state, getters, rootState, rootGetters }, payload ) { commit('increment') } }, modules: { a, b } }) // modules/a.ts import { Module } from 'vuex' import { AModuleState, RootState } from '../type' const a: Module<AModuleState, RootState> = { state: { a: 1 }, getters: { getA(state, getters, rootState) { return state.a + rootState.count } } } export default a // modules/b.ts import { Module } from 'vuex' import { BModuleState, RootState } from '../type' const b: Module<BModuleState, RootState> = { state: { b: 1 }, getters: { getB(state, getters, rootState) { return state.b + rootState.count } } } export default b
使用
1、组合式API中使用
<script setup lang="ts">
import { useStore } from '@/vuex-store'
import { computed } from 'vue';
const store = useStore()
const count = computed(() => store.state.count)
</script>
<template>
<div>
<h1>404</h1>
<p>root->count:{{ count }}</p>
<p>root->double:{{ store.getters.double }}</p>
<p>a->a:{{ store.state.a.a }}</p>
<p>b->getB:{{ store.getters.getB }}</p>
<button @click="store.commit('increment')">累加</button>
<button @click="store.dispatch('increment')">累加</button>
</div>
</template>
2、选项式API中使用
<template>
<div>
<h1>404</h1>
<p>{{ count }}-{{ double }}-{{ getA }}-{{ getB }}</p>
<button @click="increment">累加</button>
<button @click="increment1">累加</button>
</div>
</template>
<script lang="ts">
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex';
import { defineComponent } from 'vue';
export default defineComponent({
computed: {
...mapState(['count']),
...mapGetters(['double', 'getA', 'getB'])
},
methods: {
...mapActions(['increment']),
...mapMutations({
increment1: 'increment'
})
}
})
</script>
store订阅mutation
store.subscribe((mutation, state) => {
console.log('mutation操作', mutation, state)
})
store订阅action
store.subscribeAction((action, state) => {
console.log('action操作', action, state)
})
store.subscribeAction(
{
before(action, state) {
console.log('action操作前', action, state)
},
after(action, state) {
console.log('action操作完成', action, state)
},
error(action, state, error) {
console.log('action错误', action, state, error)
}
},
{ prepend: true }
)
配合vue中的v-modle实现双向绑定
1、组合式API
const count = computed({
get () {
return store.state.count
},
set (value) {
store.commit('updateCount', value)
}
})
2、选项式API
computed: {
message: {
get () {
return this.$store.state.obj.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}
关于命名空间
默认情况下,模块内部的 action 和 mutation 仍然是注册在全局命名空间的。使用 namespaced: true 添加命名空间。使用root: true 将命名空间内的属性添加到根。
1、选项式API组件中使用
// 直接通过嵌套名使用
...mapGetters([
'some/nested/module/someGetter',
'some/nested/module/someOtherGetter',
])
// 定义公共父模块
...mapGetters('some/nested/module', [
'someGetter',
'someOtherGetter',
])
// 使用createNamespacedHelpers创建基于某个命名空间辅助函数
import { createNamespacedHelpers } from 'vuex'
const { mapGetters, mapActions } = createNamespacedHelpers('some/nested/module')
...mapGetters([
'someGetter',
'someOtherGetter',
])
2、组合式Api组件中使用
const store = useStore()
store.commit('a/addA')
组合式API中使用,和选项式API通过this.$store使用方法一样,如果嫌命名空间太长,不好操作,可自己封装一个createNamespacedHelpers函数。
动态注册模块
store.registerModule('myModule', {
// ...
})
// 注册嵌套模块 `nested/myModule`
store.registerModule(['nested', 'myModule'], {
// ...
})
结语
一个广泛使用的Vue状态管理库,功能强大。做小项目练手的话,可以看看新兴的pinia。