我可以动态地将计算出的属性插入Vue组件

时间:2018-10-01 00:56:12

标签: vue.js vuejs2 vue-component computed-properties

我通过遍历大量对象来生成Vue组件的内容。我想使用计算出的属性来确定是否显示某些节点​​,但是由于计算出的引用是在循环内使用的,因此我需要能够动态设置引用名称。

下面是我正在尝试做的一个概念性示例。如何根据当前项目更改showItemX

<template>
  <ul>
    <li v-for="item in myArr" v-if="showItemX">
      {{ item.name }}
    </li>
  </ul>
</template>
<script>
  export default {
    data() {
      return {
        myArr: [{
          id: 'item1',
          name: 'Item 1'
        }, {
          id: 'item2',
          name: 'Item 2'
        }]
      };
    },
    computed: {
      showItem1: function() {
        return this.$store.state.showItem1;
      },
      showItem2: function() {
        return this.$store.state.showItem2;
      }
    }
  }
</script>

2种可能的解决方案

到目前为止,这是我考虑过的两条路线,但是我不确定哪条路线会更有效,或者是否会首选另一种方式:

1。返回计算属性的单个对象

在此选项中,上面的两个计算的属性将合并为一个属性:

computed: {
  showItem: function() {
    return {
      item1: this.$store.state.showItem1,
      item2: this.$store.state.showItem2
    }
  }
}

然后将v-if设置为showItem[item.id]

<li v-for="item in myArr" v-if="showItem[item.id]">
  {{ item.name }}
</li>

这里的缺点是,每次依赖项之一更改时,整个对象似乎都会重新计算。

2。使用一种方法来获取相应的计算属性

在这里,我尝试将item.id传递给方法,以访问相应的计算属性:

computed: {
  item1Show: function() {
    return this.$store.state.showItem1;
  },
  item2Show: function() {
    return this.$store.state.showItem2;
  }
},
methods: {
  showItem: function(id) {
    return this[id + 'Show']
  }
}

在模板中:

<li v-for="item in myArr" v-if="showItem(item.id)">
  {{ item.name }}
</li>

同样,在此示例中,我不确定是否可以充分利用计算出的属性。


这些选项中的一个应该比另一个更受青睐吗?还是有更好的方法来实现我所缺少的呢?

2 个答案:

答案 0 :(得分:0)

关于Vue和JavaScript的好处是,您可以使用任何适合您需要的方法,但是,首先,我可能会找到类似以下最容易理解的内容

<li v-for="item in myArr" v-if="showItem(item)">
    {{ item.name }}
</li>

然后定义showItem方法,例如

showItem(item) {
    return item.id === "item1" ?
        this.$store.state.showItem1 :
        this.$store.state.showItem2;
}

假设您没有在帖子中未显示的其他地方使用计算所得的属性

答案 1 :(得分:0)

有更好的方法。

对于可能的解决方案#1,您最好也这样做

<li v-for="(item, index) in myArr" v-if="$store.state['showItem' + (index + 1)]">

可能的解决方案#2,您完全会错过Vue的优化。 该方法虽然不占用大量计算资源,但将为每个渲染器的每个元素重新运行。

以下是适合您示例问题的特定参数的解决方案。但是,这实际上不是我在这里推荐的。下面有更多内容。

<template>
      <ul>
        <!--
          `:key` is crucial for performance.
          otherwise, every element will re-render 
          whenever the filtered array updates.
        -->
        <li v-for="item in myFilteredArr" :key="item.id">
          {{ item.name }}
        </li>
      </ul>
</template>

<script>
  export default {
    data: _ => ({
      myArr: [
        {
          id: 'item1',
          name: 'Item 1'
        }, 
        {
          id: 'item2',
          name: 'Item 2'
        }
      ],
    }),

    computed: {
      myFilteredArr () {
        /* 
          abstracting state to a constant avoids 
          re-running the getter functions each iteration
        */
        const state = this.$store.state;
        return this.myArr.filter(
          (item, index) => state['showItem' + (index + 1)]
        );
      }
    }

  }
</script>

我的实际建议是将所有这些逻辑转移到Vuex吸气剂中。您可以在这里阅读有关它们的信息:https://vuex.vuejs.org/guide/getters.html

由于您的过滤逻辑已在商店中处理,因此可以将设置所有showItem的函数剪切并粘贴到Vuex getter中,以相同的方式返回myFilteredArr如上所述。

这样,就没有组件<->商店相互依赖,并且商店的状态将更加整洁。