如何使用 vue + typescript 编写页面 ( vuex装饰器补充部分--store装饰器 )

5,480 阅读2分钟

本章是对上一章 如何使用 vue + typescript 编写页面 ( vuex装饰器部分 )的补充 ,感谢 @慕容寒江 的提出建议

在使用store装饰器之前,先过一下传统的store用法吧

export default  {
    namespaced:true,
    state:{
        foo:""
    },
    getters:{
        getFoo(state){ return state.foo}
    },
    mutations:{
        setFooSync(state,payload){
            state.foo = payload
        }
    },
    actions:{
        setFoo({commit},payload){
            commot("getFoo",payload)
        }
    }
}

然后开始使用vuex-module-decorators

import {
Module,
VuexModule, 
Mutation, 
Action, 
MutationAction, 
getModule } from 'vuex-module-decorators'

1. VuexModule 用于基本属性

export default class TestModule extends VuexModule { }

VuexModule 提供了一些基本属性,包括namespaced,state,getters,modules,mutations,actions,context 其中context则会在接下来的代码中使用到

2. @Module 标记当前为module

@Module
export default class TestModule extends VuexModule {
    /* 这里代表的就是state里面的状态 */
    inlineState = "";
    /* 这里就是 getters 里面的内容*/
    get named(){
        return 1;
    }
}

module本身有几种可以配置的属性

  • namespaced:boolean 启/停用 分模块
  • stateFactory:boolean 状态工厂[我也不知道干什么的,有知道的可以留言]
  • dynamic:boolean 在store创建之后,再添加到store中。 开启dynamic之后必须提供下面的属性
  • name:string 指定模块名称
  • store:Vuex.Store实体 提供初始的store

dynamic 模式

动态模式为反向注入store。

常规下是

export default new Vuex.Store({
    modules:{  TestModule }
})

开启后为

// store.ts
export default new Vuex.Store({
    modules:{  /* 其余的store */ }
})
import store from './store'
@Module({
    dynamic:true,
    name: "TestModule", 
    store
})
export default class TestModule extends VuexModule { }
// 在需要引用的地方单独引用该store文件即可注入。
// 好处:灵活使用,仅仅在需要引入的地方才注入到store中去
// 缺点:需要单独引入文件

3. @Mutation 标注为mutation

@Module
export default class TestModule extends VuexModule {
    inlineState = "";
    @Mutation
    setInlineStateSync(inlineState:string){
        this.inlineState = inlineState;
    }
}

4. @Action 标注为action

用法和@Emit很相似

@Module
export default class TestModule extends VuexModule {

    @Action({ commit: 'setInlineStateSync' })
    setInlineState(inlineState:string){
        /*这里使用自动提交*/
        return inlineState;
    }
    @Action
    setInlineStateContext(inlineState:string){
        /* 这里使用手动提交 */
        this.context.commit("setInlineStateSync",inlineState)
    }
}

5. @MutationAction

这个属性可以直接映射属性,

  • mutate 提供属性列表
@Module
export default class TestModule extends VuexModule {
    
    foo = "";
    doo = "";
    
    @MutationAction({mutate:["foo","doo"]/*提供需要映射的属性列表*/})
    async setMutationAction(payload:{foo:string,doo:string} /* 传入的payload对象属性需要和mutate的名称一致*/){
        /* 这里如果有返回,则必须返回一个Promise<{foo:string,doo:string}>类型*/
        /* 但是在使用时,则有很奇葩的事情*/
        /* 如果映射为Mutation [ @Mutation("TestModule/setMutationAction") ],则不会执行函数本身, 使用传入的值作为结果*/
        /* 如果映射为Action [ @Action("TestModule/setMutationAction") ],会执行函数本身并且得到的返回值为结果 */
    }
}

6. getModule 得到一个类型安全的store,module必须提供name属性

@Module({ name : "tm" })
export default class TestModule extends VuexModule {
    
}

常规,需要提供store,即:

getModule(TestModule,this.$store).inlineState  // "inlineState value"

开启dynamic时,不需要提供store,因为module本身已经注入store。

 getModule(TestModule).inlineState  // "inlineState value"

更多内容参照vuex-module-decorators 或者 github:vuex-module-decorators