使用TypeScript+Vuex

2,705 阅读2分钟

准备工作

1,使用vue-cli 3搭建Vue项目,如果不知道怎么搭建的同学可以点击这里

2,使用 npm i -s vuex-class 命令安装 vuex-class

3,删除src/store.ts(很重要)

4,根目录下新建如下文件


5,代码如下

store/types.ts 

  • 声明并暴露 RootState 类型
// store/types.ts

import { UserState } from './user/types'

export interface RootState {
  user: UserState
}


store/index.ts

  • 使用StoreOptions类型定义Vuex.Store构造器选项的类型,并将RootState作为泛型传入StoreOptions,用来定义根状态的类型
  • RootState作为泛型,传入Vuex.Store构造器

// store/index.ts

import Vue from 'vue'
import Vuex, { StoreOptions } from 'vuex'
import { RootState } from './types'
import { user } from './user/index'Vue.use(Vuex)

const store: StoreOptions<RootState> = {
  modules: {
    user
  }
}
export default new Vuex.Store<RootState>(store)


store/user/types.ts

  • 声明并暴露UserState类型

// store/user/types.ts

export interface UserState {
  firstName: string
  lastName: string
  mobile: string
}


store/user/actions.ts

  • 使用ActionTree定义actions的类型,并将UserStateRootState作为泛型传入ActionTree

// store/user/actions.ts

import { UserState } from './types'
import { ActionTree } from 'vuex'
import { RootState } from '../types'

export const actions: ActionTree<UserState, RootState> = {
  fetchData({ commit }): void {
    const userInfo: UserState = {
      firstName: 'Hello',
      lastName: 'World',
      mobile: '1235678911'
    }
    commit('saveUserInfo', userInfo)
  }
}


store/uset/getters.ts

  • 使用GetterTree定义getters的类型,并将UserStateRootState作为泛型传入GetterTree

// store/user/getters.ts

import { GetterTree } from 'vuex'
import { UserState } from './types'
import { RootState } from '../types'

export const getters: GetterTree<UserState, RootState> = {
  fullName(state): string {
    return `${state.firstName} ${state.lastName}`
  }
}


store/user/mutations.ts

  • 使用MutationTree定义mutations的类型,并将UserState作为泛型传入MutationTree
  • MutationTree不需要传入RootState

// store/user/mutations.ts

import { MutationTree } from 'vuex'
import { UserState } from './types'

export const mutations: MutationTree<UserState> = {
  changeMobile(state, mobile: string) {
    state.mobile = mobile
  },
  saveUserInfo(state, userInfo) {
    state = Object.assign(state, userInfo)
  }
}


store/user/index.ts

  • 使用UserState定义user模块的state的类型
  • 使用Module定义user模块的类型,并将UserStateRootState作为泛型传入Module
// store/user/index.ts

import { Module } from 'vuex'
import { UserState } from './types'
import { RootState } from '../types'
import { getters } from './getters'
import { actions } from './actions'
import { mutations } from './mutations'

const state: UserState = {
  firstName: '',
  lastName: '',
  mobile: ''
}
const namespaced = true
export const user: Module<UserState, RootState> = {
  namespaced,
  state,
  getters,
  actions,
  mutations
}
export default state

开始使用

1,使用 namespace('path/to/module') 装饰器

import { Component, Vue } from 'vue-property-decorator'
import { namespace } from 'vuex-class'

const userModule = namespace('user')

@Component
export default class Home extends Vue {
  @userModule.Action('fetchData') public fetchData!: Function
  @userModule.Mutation('changeMobile') public changeMobile!: Function
  @userModule.Getter('fullName') public fullName!: string
  @userModule.State('firstName') public firstName!: string
  @userModule.State('mobile') public mobile!: string
  public created() {
    this.fetchData()
    this.changeMobile('123456')
  }
}

等同于使用下面的js写法:

import { createNamespacedHelpers } from 'vuex'

const {
  mapState,
  mapMutations,
  mapGetters,
  mapActions
} = createNamespacedHelpers('user')

export default {
  computed: {
    ...mapState(['firstName', 'mobile']),
    ...mapGetters(['fullName'])
  },
  methods: {
    ...mapActions(['fetchData']),
    ...mapMutations(['changeMobile'])
  },
  created() {
    this.fetchData()
    this.changeMobile('123456')
  }
}

2,使用@Action('action', { namespace: 'path/to/module' })这种形式

import { Component, Vue } from 'vue-property-decorator'
import { Action, Mutation, Getter, State } from 'vuex-class'

const namespace = 'user'

@Component
export default class Home extends Vue {
  @Action('fetchData', { namespace }) public fetchData!: Function
  @Mutation('changeMobile', { namespace }) public changeMobile!: Function
  @Getter('fullName', { namespace }) public fullName!: string
  @State('firstName', { namespace }) public firstName!: string
  @State('mobile', { namespace }) public mobile!: string

  public created() {
    this.fetchData()
    this.changeMobile('123456')
  }
}

3,使用 @Action('path/to/module/action') 这种形式

注意:@State装饰器不能使用这种方式

import { Component, Vue } from 'vue-property-decorator'
import { Action, Mutation, Getter, State } from 'vuex-class'

const namespace = 'user'

@Component
export default class Home extends Vue {
  @Action('user/fetchData') public fetchData!: Function
  @Mutation('user/changeMobile') public changeMobile!: Function
  @Getter('user/fullName') public fullName!: string
  @State('firstName', { namespace }) public firstName!: string
  @State('mobile', { namespace }) public mobile!: string

  public created() {
    this.fetchData()
    this.changeMobile('123456')
  }
}

参考:codeburst.io/vuex-and-ty…