admin管理员组

文章数量:1192918

I have a Vue component like this:

<script>
import { mapActions, mapGetters } from 'vuex'

export default {
  props: ['index'],
  computed: {
    ...mapGetters([
      'type',
      'width',
      'height',
      'description',
      'smtTagMeasureUnits',
      'tagValue'
    ])
  }
</script>

<template>
  <div :class='["block","module-"+type(index), "width"+width(index), "height"+height(index)]'>
    <h3>{{ description(index) }}</h3>
    <div class="data">
      <h1>{{ tagValue(index) }}</h1>
      <h2 class="measure">{{ smtTagMeasureUnits(index) }}</h2>
    </div>
  </div>
</template>

<style>
  ...
</style>

Parameter index, which comes into component as a prop, has been successfully passed to getters:

getters: {
  ...
  type: (state, getters) => (par) => {
    return getters.widgetsConfig[par].type
  },
  width: (state, getters) => (par) => {
    if (getters.widgetsConfig[par].width) {
      return getters.widgetsConfig[par].width
    } return 2
  },
  height: (state, getters) => (par) => {
    if (getters.widgetsConfig[par].height) {
      return getters.widgetsConfig[par].height
    } return 1
  },
  ...
}

Works fine, but i'm not happy with this codestyle, because getterName(index) constantly repeats in the template part. All of my getters should carry index as a prop, so i'd like to have just getterName in the template and something like this in the script part:

...mapGetters([
'type',
'width',
'height',
'description',
'smtTagMeasureUnits',
'tagValue'
], index)

Is it possible to achieve any codestyle improvements here?

I have a Vue component like this:

<script>
import { mapActions, mapGetters } from 'vuex'

export default {
  props: ['index'],
  computed: {
    ...mapGetters([
      'type',
      'width',
      'height',
      'description',
      'smtTagMeasureUnits',
      'tagValue'
    ])
  }
</script>

<template>
  <div :class='["block","module-"+type(index), "width"+width(index), "height"+height(index)]'>
    <h3>{{ description(index) }}</h3>
    <div class="data">
      <h1>{{ tagValue(index) }}</h1>
      <h2 class="measure">{{ smtTagMeasureUnits(index) }}</h2>
    </div>
  </div>
</template>

<style>
  ...
</style>

Parameter index, which comes into component as a prop, has been successfully passed to getters:

getters: {
  ...
  type: (state, getters) => (par) => {
    return getters.widgetsConfig[par].type
  },
  width: (state, getters) => (par) => {
    if (getters.widgetsConfig[par].width) {
      return getters.widgetsConfig[par].width
    } return 2
  },
  height: (state, getters) => (par) => {
    if (getters.widgetsConfig[par].height) {
      return getters.widgetsConfig[par].height
    } return 1
  },
  ...
}

Works fine, but i'm not happy with this codestyle, because getterName(index) constantly repeats in the template part. All of my getters should carry index as a prop, so i'd like to have just getterName in the template and something like this in the script part:

...mapGetters([
'type',
'width',
'height',
'description',
'smtTagMeasureUnits',
'tagValue'
], index)

Is it possible to achieve any codestyle improvements here?

Share Improve this question edited Nov 13, 2018 at 21:35 KrasnokutskiyEA asked Nov 13, 2018 at 21:26 KrasnokutskiyEAKrasnokutskiyEA 5971 gold badge6 silver badges22 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 17

If you want to keep things DRY, it would make sense to leverage logic of getting item (entity that index corresponds to) information to the store, so component only receives full data that is ready to be rendered.

Suggested solution is to create a single getter, that accepts index as an argument and returns full list of options from getters.widgetsConfig.

Note that if needed other getters may be re-used in order to collect necessary information into a single object.

Possible implementation:

getters: {
  ...
  getItemByIndex: (state, getters) => (index) => {
    const { type, height, width } = getters.widgetsConfig[index]
    return {
      type,
      height,
      width
    }
  },
}

And update component to map a single getter and use it in computed property:

computed: {
  ...mapGetters([
    'getItemByIndex'
  ]),
  item () {
    return this.getItemByIndex(index)
  }
}

And all properties will be accessible inside a template via item.type, item.height, item.width, etc..

You can always make computed properties that return the result of the getters. Something like:

export default {
  props: ['index'],
  computed: {
    ...mapGetters([
      'getTypeFromIndex',
      'getWidthFromIndex',
      'getHeightFromIndex'
    ]),
    height(): { return this.getHeightFromIndex(index) },
    width(): { return this.getWidthFromIndex(index) },
    type(): { return this.getTypeFromIndex(index) },

    //going a step further to clean up your templates...
    classList: [
        "block", 
        "height"+this.height,
        "width"+this.width,
    ]
  }

That way you just need height in your templates instead of height(index), or even just classList if you take it that far

This is also referenced here: https://github.com/vuejs/vuex/issues/688 and I can't find it but I know I've seen that recommended by Evan You in a github issue as well.

本文标签: javascriptpass parameter to getters in VuexStack Overflow