VueJS计算属性与v-if性能

时间:2019-07-17 19:41:24

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

我有一个数据数组,并且数组中的每个项目都有一个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将其显示在自己的部分中。

通过API调用来更改state,因此我需要将item和新状态的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-if相同的元素上使用v-for。但是,即使它减少了我的应用程序的时间复杂度,我仍然应该避免它吗?

当前场景:
3个计算的属性(O(3n))+ findIndex(O(n))+ 3个v-for(O(p + r + q))

条件v-for
3个条件v-for(O(3n))(没有findIndex,这样我可以将索引直接传递给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>

2 个答案:

答案 0 :(得分:0)

目前尚不清楚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>

答案 1 :(得分:0)

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

将数据作为对象。通过这种方式找到值将是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,因为您已经在不同的列表上进行了迭代。