当前位置: 首页 > 工具软件 > vuex-cli > 使用案例 >

Vue3+Typescript项目构建之Vuex模块化搭建(vuex-module-decorators)

谭俊
2023-12-01

相比起Vue2项目构建Vuex模块化,Vue3 + Typescript构建Vuex模块化有着很大的不同。

安装vuex-module-decorators

这是一个帮助我们快速安全高效构建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'
  ]
}

用法详解

state

// 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

getters

// 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) };
  }
}

mutations

// 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

actions

// 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)
	   }
	}
}

MutationActions

同样的道理
欢迎看文档

在文件中使用

第一种

第一种适用于使用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>

作者推荐使用第一种方式

 类似资料: