相比起Vue2
项目构建Vuex模块化,Vue3 + Typescript
构建Vuex
模块化有着很大的不同。
这是一个帮助我们快速安全高效构建Vuex模块的npm包,官方文档。
npm install vuex-module-decorators
# or
yarn add vuex-module-decorators
在Vue CLI
创建的项目中,记得在vue.config.js
配置里添加转译配置(ES6 to ES5),并且兼容IE11。
// vue.config.js
module.exports = {
// ... your other options
transpileDependencies: [
'vuex-module-decorators'
]
}
// store/modules/user.js
import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
import store from '@/store'
@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule {
count = 20
}
export const UserModule = getModule(User)
等同于以下写法
export default {
state: {
count: 20
}
}
如果无法确定状态值,那么必须给他赋初始值
null
,就像这样count: number | null = null
// store/modules/user.js
import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
import store from '@/store'
@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule {
count = 20
get halfCount() {
return this.count / 2
}
}
export const UserModule = getModule(User)
等同于以下写法
export default {
state: {
count: 20
},
getters: {
halfCount: state => state.count / 2
}
}
如何你想在getters
里处理一些复杂数据
// store/modules/user.js
@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule {
companies = []
get company() {
return (companyName: string) => { this.companies.find(company => company.name === companyName) };
}
}
// store/modules/user.js
import { Module, VuexModule, Mutation } from 'vuex-module-decorators'
@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule {
count = 20
@Mutation
REDUCE_COUNT(payload: number) {
this.count = this.count - payload
}
}
export const UserModule = getModule(User)
等同于以下写法
export default {
state: {
count: 20
},
mutations: {
REDUCE_COUNT: (state, payload) => {
state.count = state.count - payload
}
}
}
使用
this
即可指代state
// store/modules/user.js
@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule {
@Action
dispatchReduce(payload: number) {
this.context.commit('REDUCE_COUNT', payload)
}
}
export const UserModule = getModule(User)
等同于以下写法
export default {
state: {
count: 20
},
actions: {
REDUCE_COUNT: ({ commit }, payload) => {
commit('REDUCE_COUNT', payload)
}
}
}
同样的道理
欢迎看文档
第一种适用于使用
getModule
导出的模块
即代码里是这样写的
class User extends VuexModule{}
export const UserModule = getModule(User)
// store/modules/user.js
import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
import store from '@/store'
@Module({ dynamic: true, store, namespaced: true, name: 'user' })
class User extends VuexModule {
// TODO
}
export const UserModule = getModule(User)
// store/index.ts
import { createStore } from 'vuex'
export default createStore({})
<!-- index.vue --->
<template>
<div class="home">
<h1 class="text">Home</h1>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { UserModule } from '@/store/modules/user'
export default defineComponent({
name: 'Home',
setup() {
const myhalfCount = UserModule.halfCount
UserModule.dispatchReduce(5)
console.log(myhalfCount) // 10
console.log(UserModule.count) // 15
},
components: {}
})
</script>
适用于以下写法,把
@Module里的dynamic: true
去掉
@Module({ store, namespaced: true, name: 'user' })
export default class User extends VuexModule{}
// store/modules/user.js
import { Module, VuexModule, Mutation, Action, getModule } from 'vuex-module-decorators'
import store from '@/store'
@Module({ store, namespaced: true, name: 'user' })
export default class User extends VuexModule {
// TODO
}
// store/index.ts
import { createStore } from 'vuex'
import UserModule from '~/store/modules/user'
export default createStore({
modules: {
user: UserModule // 此处键名必须和@Module里name的值一样
}
})
<!-- index.vue --->
<template>
<div class="home">
<h1 class="text">Home</h1>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import store from '@/store'
export default defineComponent({
name: 'Home',
setup() {
console.log(store.state.user.count) // 20
},
components: {}
})
</script>
作者推荐使用第一种方式