【问题标题】:VueJS computed property vs v-if, performanceVueJS 计算属性 vs v-if,性能
【发布时间】:2019-07-18 05:03:38
【问题描述】:

我有一个数据数组,数组中的每个项目都有一个 state 属性,其中包含以下值之一:allowedpendingrejected。我想根据他们的state 在单独的部分中显示数据。每张数据卡上有两个按钮,可用于更改项目state

我使用三个计算属性来分隔数据,如下所示:

computed: {
    pendingData() {
        return this.data.filter(x => x.state === 'pending')
    },
    allowedData() {
        return this.data.filter(x => x.state === 'allowed')
    },
    rejectedData() {
        return this.data.filter(x => x.state === 'rejected')
    }
}

然后我使用v-for 将它们显示在自己的部分中。

更改state是通过API调用发生的,所以我需要将项目的id和新状态发送到setState函数:

<div class="state-change-buttons">
    <button @click="setState(item.id, 'allowed')">
        <span uk-icon="icon: check; ratio: 1.4"></span>
    </button>
    <button @click="setState(item.id, 'pending')">
        <span uk-icon="icon: future; ratio: 1.4"></span>
    </button>
</div>

这是setState函数:

setState(id, state) {
    const index = this.data.findIndex(x => x.id === id)
    this.$axios.post(`/api/${id}`, {state})
        .then(res => {
            this.data.splice(index, 1, res.data)
        })
        .catch(err => {
            this.$notify(err, 'danger')
        })
}

如您所见,要实时更新我的​​数据数组,我必须使用findIndex 找到所选项目的索引。

Vue style guide 建议不要在与v-for 相同的元素上使用v-if。但是我是否仍然应该避免它,即使它降低了我的应用程序的时间复杂度?

当前情况:
3 计算属性 (O(3n)) + findIndex (O(n)) + 3 v-for (O(p + r + q))

有条件的v-for:
3个条件v-for(O(3n))(没有findIndex,这样我可以直接把index传给setState

条件v-for代码:

<div v-for="(item, index) in data" v-if="item.state === 'pending'" :key="item.id">
    <!-- data card body (including buttons) -->
</div>

<div v-for="(item, index) in data" v-if="item.state === 'allowed'" :key="item.id">
    <!-- data card body (including buttons) -->
</div>

<div v-for="(item, index) in data" v-if="item.state === 'rejected'" :key="item.id">
    <!-- data card body (including buttons) -->
</div>

【问题讨论】:

标签: javascript performance vue.js vuejs2 time-complexity


【解决方案1】:

尚不清楚v-if 与父母或孩子有关。您可以使用模板来解决此问题:

<template v-for="(item, index) in data">
  <div v-if="item.state === 'rejected'" :key="item.id">
    <!-- data card body (including buttons) -->
  </div>
</template>

【讨论】:

  • 反之,v-for优先级更高。
【解决方案2】:

正如对您问题的评论所说,如果没有看到 2 个建议的模板,我也无法理解您的计算。 不过,这是我在面对此类列表时的个人偏好。

将数据作为对象。这样找到值将是 O(1)。并且会增加可读性。还将数组作为计算属性。

export default {
  name: 'list',
  data: () => ({
    data: {
      'id1': {id: 'id1', state: 'pending'},
      'id2': {id: 'id2', state: 'allowed'},
      'id3': {id: 'id3', state: 'rejected'},
    },
  }),
  computed: {
    dataList() {
      return Object.values(this.data)
    },
    pendingData() {
        return this.dataList.filter(x => x.state === 'pending')
    },
    allowedData() {
        return this.dataList.filter(x => x.state === 'allowed')
    },
    rejectedData() {
        return this.dataList.filter(x => x.state === 'rejected')
    },
  },
  methods: {
    setState(id, state) {
    this.$axios.post(`/api/${id}`, {state})
      .then(res => {
          Object.assign(this.data[id], res.data);
      })
      .catch(err => {
          this.$notify(err, 'danger')
      })
    }
  }
};

然后你就在模板中这样使用:

<div v-for="item of pendingData" :key="item.id">
    <!-- data card body (including buttons) -->
</div>

<div v-for="item of  allowedData" :key="item.id">
    <!-- data card body (including buttons) -->
</div>

<div v-for="item of rejectedData" :key="item.id">
    <!-- data card body (including buttons) -->
</div>

注意:在作者对我的回复发表评论后,代码已更改。所以这样你就可以避免 v-if 因为你已经在迭代不同的列表了。

【讨论】:

  • 没有过滤器之类的东西。所有三个列表同时呈现。模板中唯一的区别是v-if被添加到v-fors,所以计算属性和findIndex被省略了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-14
  • 2020-02-05
  • 2018-02-21
  • 2017-08-23
  • 2018-01-02
  • 2019-02-11
相关资源
最近更新 更多