【问题标题】:How to use mapActions with vue + Typescript class component?如何将 mapActions 与 vue + Typescript 类组件一起使用?
【发布时间】:2020-05-22 18:09:15
【问题描述】:

我想知道在 Typescript vue 类组件中使用 ...mapActions([]) 的正确方法是什么。

这就是我的做法:

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import { mapActions } from "vuex";

@Component
export default class UsersAdd extends Vue {
  userName: string = "";

    ...mapActions(["newUser"]) /*mapAction from vuex */
  addUser() {
    console.log("...adding new user");
    this.newUser(this.userName);
  }
}
</script>

你可以说它不工作......

使用 Javascript 我是这样做的。

methods:{
  ...mapActions(["newUser"])
}

如何使用 Typescript 类组件?

编辑: 这个方法我试过了,还是不行

@Component({
  methods: {
    ...mapActions(["newUser"]) /*mapAction from vuex */
  }
})
export default class UsersAdd extends Vue {
  userName: string = "";

  addUser() {
    console.log("...adding new user");
    this.newUser(this.userName);
  }
}

【问题讨论】:

  • 语法无效。不会有好的方法,因为 TS 不会知道您尝试添加的方法。请参阅github.com/vuejs/vue-class-component/issues/… 了解解决方法。
  • @EstusFlask 您共享的链接将与 mapGetters 一起使用,但如果我使用方法: mapActions([]) 然后在 addUser() 中调用它,它将无法工作
  • 会导致类型错误吗?您还需要手动输入方法,请参阅链接中的charts!: any[]。我想在你的情况下它需要是newUser!: (username: string) =&gt; void

标签: typescript vue.js vuejs2 vue-component vuex


【解决方案1】:

如果您不想引入另一个依赖项(即vuex-class)。我们可以将 store 中的操作映射到 Typescript 中的组件,如下所示:

@Component({
  computed: {
    ...mapActions({
      someLoadDataAction: "someLoadDataAction"
    })
  }
})
export default class HelloWorld extends Vue {
  someLoadDataAction!: () => any;

  mounted() {
    console.log(this.someLoadDataAction);
  }
}

关键是添加这个someLoadDataAction!: () =&gt; any 用于Typescript 的静态类型检查。例如,我们将函数类型定义为() =&gt; any,但您可以将其更改为vuex 存储中操作的实际返回类型。

【讨论】:

  • 我尝试将字符串作为参数传递给 someLoadDataAction,但它在 someLoadDataAction 方法内的变量中捕获了一个未知对象?
【解决方案2】:

在 Action 注释的帮助下,您可以这样做。 安装npm install --save vuex-class

import { Action } from 'vuex-class'

@Component()
export default class UsersAdd extends Vue {
  userName: string = "";

  @Action('newUser')
  newUser!: (newUser: string) => void
  addUser() {
    console.log("...adding new user");
    this.newUser(this.userName);
  }
}

【讨论】:

    【解决方案3】:

    其他选项,您可以使用vuex-module-decorators 更好地支持typescript 并减少代码。

    安装

    npm install -D vuex-module-decorators
    

    存储/索引.ts

    import { Action, getModule, Module, Mutation, VuexModule } from "vuex-module-decorators";
    import store from "..";
    
    // define Mutations name
    enum Mutations {
      NEW_USER_NAME = "NEW_USER_NAME"   
    }
    
    // name: module name
    // dynamic: true,dynamic create module
    // namespaced: true,using namespaced
    // store: your root store/index.ts
    @Module({ name: 'UserStore', dynamic: true, namespaced: true, store })
    export default class UserStore extends VuexModule {
      // state
      userName = '';
    
      // mutation
      @Mutation
      [Mutations.NEW_USER_NAME](userName: string) {
        this.userName = userName;
      }
    
      // action
      @Action
      newUser(userName: string) {
        this.context.commit(Mutations.NEW_USER_NAME, userName);
      }
    }
    
    // use getModule to safe get instance
    export const userStore = getModule(UserStore);
    

    UsersAdd.vue

    import { userStore } from "@/store/modules/user";
    @Component()
    export default class UsersAdd extends Vue {
      userName: string = "";
       
      addUser() {    
        console.log("...adding new user");     
        userStore.newUser(this.userName);
      }
    }
    

    【讨论】:

      【解决方案4】:

      另一种方法是使用自定义装饰器,它将组件中的方法替换为 vuex 存储中的方法。

      function VuexAction(moduleName: string): any {
        return createDecorator((options: any, key: string) => {
          if (!options.methods) options.methods = {};
          options.methods[key] = function wrapperMethod(...args: any[]) {
            return this.$store._actions[`${moduleName}/${key}`][0](...args);
          };
        });
      }
      

      装饰器可以这样使用:

      @Component
      export default class SomeComponent extends Vue {
        @VuexAction("vuexModuleName") vuexModuleActionName!: () => void;
      
        async doStuff () {
          this.vuexModuleActionName();
        }
      }
      

      这个想法基于关于自定义装饰器的文档:

      https://class-component.vuejs.org/guide/custom-decorators.html

      还有一个自定义的 vuex getter 装饰器:

      https://github.com/vuejs/vue-class-component/issues/56#issuecomment-272604193

      【讨论】:

        猜你喜欢
        • 2020-03-02
        • 2017-01-26
        • 2018-04-16
        • 2019-07-31
        • 2020-06-01
        • 2017-11-20
        • 2017-09-15
        • 2018-06-02
        • 2021-12-31
        相关资源
        最近更新 更多