Vue-class-component: how to use with vuex

Created on 12 Jan 2017  路  5Comments  路  Source: vuejs/vue-class-component

How can i use mapActions, or mapGetters with using classes?

in vuex they use:

computed: {
...mapState('foo', {
// state is the state of the foo/ module instead of root
bar: state => state.bar
}
},
methods: {
...mapActions('foo', [
// map this.doSomething() to this.$store.dispatch('foo/doSomething')
'doSomething'
])
}

Most helpful comment

We can specify component options object to @Component decorator, so you can just use these helpers.

@Component({
  computed: {
    ...mapState('foo', {
      bar: state => state.bar
    }
  },
  methods: {
    ...mapActions('foo', [
      'doSomething'
    ])
  }
})

If you would like to write as more class-like style, I encourage you to write some custom decorators.

function Getter (getterType) {
  return createDecorator((options, key) => {
    if (!options.computed) options.computed = {}
    options.computed[key] = function () {
      return this.$store.getters[getterType]
    }
  })
}

@Component
class MyComp extends Vue {
  @Getter('foo') bar

  created () {
    console.log(this.bar)
  }
}

All 5 comments

We can specify component options object to @Component decorator, so you can just use these helpers.

@Component({
  computed: {
    ...mapState('foo', {
      bar: state => state.bar
    }
  },
  methods: {
    ...mapActions('foo', [
      'doSomething'
    ])
  }
})

If you would like to write as more class-like style, I encourage you to write some custom decorators.

function Getter (getterType) {
  return createDecorator((options, key) => {
    if (!options.computed) options.computed = {}
    options.computed[key] = function () {
      return this.$store.getters[getterType]
    }
  })
}

@Component
class MyComp extends Vue {
  @Getter('foo') bar

  created () {
    console.log(this.bar)
  }
}
function MapGetters (namespace, states) {
  return createDecorator(options => {
    if (!options.computed) {
      options.computed = {}
    }
    Object.assign(options.computed, mapGetters(namespace, states))
  })
}

@Component
class MyComp extends Vue {
  @MapGetters('some/namespace', ['getter1', 'getter2'])

  created () {
    console.log(this.getter1, this.getter2)
  }
}

I found this way more functional and common with vue style

If you are using Typescript I would recommend @ktsn solution

function Getter (getterType) {
  return createDecorator((options, key) => {
    if (!options.computed) options.computed = {}
    options.computed[key] = function () {
      return this.$store.getters[getterType]
    }
  })
}

@Component
class MyComp extends Vue {
  @Getter('foo') bar

  created () {
    console.log(this.bar)
  }
}

I couldn't get @ktsn's code to work. As far as I can tell these are the types:

import { createDecorator, VueDecorator } from 'vue-class-component';
import { ComponentOptions } from 'vue';

function Getter(getterName: string): VueDecorator {
  return createDecorator((options: ComponentOptions<Vue>, key: string, index: number): void => {
    if (options.computed === undefined) {
      options.computed = {};
    }
    options.computed[key] = function(this: Vue) {
      return this.$store.getters[getterName];
    };
  });
}

@Component
class MyComp extends Vue {
  @Getter('info')
  public info?: Info;
}

This compiles but MyComp::info doesn't get updated reactively from the store (it is always undefined). If I change it to be public info: Info | null = null then I get errors that info already exists in the data type, when it tries to set options.computer['info']. That makes sense to me. Declaring the field in the class adds it to data and the decorator adds it to computed and it can't be the same name in both, so how on earth is this supposed to work?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

backbone87 picture backbone87  路  4Comments

kabaluyot picture kabaluyot  路  3Comments

liudonghua123 picture liudonghua123  路  5Comments

micobarac picture micobarac  路  6Comments

valorad picture valorad  路  4Comments