参考:
官方文档
vuex-module-decorators
安装 npm install -D vuex-module-decorators
安装成功后就可以使用啦,先看一个完整案例
// store/modules/passenger.ts
import {Module,VuexModule,Mutation,Action,getModule,} from 'vuex-module-decorators';
import store from '@/store';
type User = { username: string; password: string; }
// dynamic: true: 动态创建动态模块,即new Vuex.Store({})里面不用注册的.空着就行,
// store,当前模块注册到store上.也可以写在getModule上,即getModule(PassengerStore,store)
// namespaced: true, name: 'passenger' 命名空间
@Module({
name: 'passenger', dynamic: true, namespaced: true, store,
})
export default class PassengerStore extends VuexModule {
// state => 要public不然外面调用不到
public loginInfo: User[] = [];
// getter
get userNumber(): number {
return this.loginInfo.length;
}
@Mutation
USERINFO(user: User): void {
console.log(user);
this.loginInfo.push(user);
}
// commit的两种调用方式,第一种,Action后面的括号里面添加commit,然后return的结果就是USERINFO的参数
@Action({ commit: 'USERINFO' })
getZhangsan(): User {
return { username: '张三', password: 'zhangsan' };
}
// 第二种,直接this.USERINFO调用;
@Action
getLisi(): void {
const user = { username: '李四', password: 'lisi' };
this.context.commit('USERINFO', user); // commit调用
// this.USERINFO(user); // 直接调用
}
}
// 使用getModule: 对类型安全的访问
export const PassengerStoreModule = getModule(PassengerStore);
// sotre/index.ts
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({ }); // 由于passenger->dynamic: true: 是动态创建动态模块,所以不需要再次注册
index.vue页面使用
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { PassengerStoreModule } from '@/store/modules/passenger';
@Component
export default class IndexPage extends Vue {
created() {
console.log(PassengerStoreModule.loginInfo); // state
console.log(PassengerStoreModule.userNumber); // getter
PassengerStoreModule.getZhangsan(); // actions
PassengerStoreModule.getLisi(); // actions
}
}
</script>
上面的案例是一个,使用了动态注册,下面我们详细说下,具体的使用
@Component state getter
@Mutations
@Actions
@MutationsActions
getModule
动态模块
state:
import { Module, VuexModule } from 'vuex-module-decorators'
@Module
export default class Vehicle extends VuexModule {
wheels = 2
}
等同于下面的代码
export default {
state: { wheels: 2 }
}
getter
import { Module, VuexModule } from 'vuex-module-decorators'
@Module
export default class Vehicle extends VuexModule {
wheels = 2
get axles() {
return this.wheels / 2
}
}
等同于下面的代码
export default {
state: { wheels: 2 },
getters: {
axles: (state) => state.wheels / 2
}
}
@Mutations
import { Module, VuexModule, Mutation } from 'vuex-module-decorators'
@Module
export default class Vehicle extends VuexModule {
wheels = 2
@Mutation
puncture(n: number) {
this.wheels = this.wheels - n
}
}
等同于下面的代码
export default {
state: { wheels: 2 },
mutations: {
puncture: (state, payload) => {
state.wheels = state.wheels - payload
}
}
}
@Actions
import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators'
import { get } from 'request'
@Module
export default class Vehicle extends VuexModule {
wheels = 2
@Mutation
addWheel(n: number) {
this.wheels = this.wheels + n
}
@Action
async fetchNewWheels(wheelStore: string) {
const wheels = await get(wheelStore)
this.context.commit('addWheel', wheels)
}
}
等同于下面的代码
const request = require('request')
export default {
state: { wheels: 2 },
mutations: {
addWheel: (state, payload) => {
state.wheels = state.wheels + payload
}
},
actions: {
fetchNewWheels: async (context, payload) => {
const wheels = await request.get(payload)
context.commit('addWheel', wheels)
}
}
}
@MutationAction
在vuex中是要通过commit来更改state中的数据.在vuex-module-decorators中有MutationAction修饰器,可以直接修改state数据.
export default class PassengerStore extends VuexModule {
public username = '';
public password = '';
//'username'和'password'被返回的对象替换,
//格式必须为`{username:...,password:...}`
@MutationAction({ mutate: ['username', 'password'] })
async setPassenger(name: string) {
const response: any = await request(name); // 接口返回 [{name:'张三',password:'123456'}]
// 此处返回值必须和上面mutate后面的名称保持一致;
return {
username: response[0].name,
password: response[0].password,
};
}
}
// index.vue中使用
<template>
<div class="">
用户名:{{PassengerStoreModule.username}}<br/>
密码:{{PassengerStoreModule.password}}<br/>
<button @click="getPassenger()">getPassenger</button>
</div>
</template>
...
@Component
export default class IndexPage extends Vue {
private PassengerStoreModule: any = PassengerStoreModule;
getPassenger() {
PassengerStoreModule.setPassenger('西施');
}
}
// 运行过后,点击getPassenger按钮,用户名和密码会发生变化哦
getModule:创建类型安全的访问
传统是需要注册到的new Vuex.Store上,然后通过this$store访问,使用getModule访问类型更加安全,
可以再module上使用store模块,然后getModule(模块名)
也可以getModule(模块名,this.$store)的形式
import { Module, VuexModule, getModule } from 'vuex-module-decorators'
import store from '@/store'
// 1. module上使用store
@Module({ dynamic: true, store, name: 'mymod' })
class MyModule extends VuexModule {
someField: number = 10
}
const myMod = getModule(MyModule)
myMod.someField //works
myMod.someOtherField //Typescript will error, as field doesn't exist
// 2. module上不使用store, getModule使用store
@Module({ dynamic: true, name: 'mymod' })
class MyModule extends VuexModule {
someField: number = 10
}
const myMod = getModule(MyModule,store)
...