我有一个数据数组,并且数组中的每个项目都有一个state
属性,该属性包含以下值之一:allowed
,pending
,rejected
。我想根据它们的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>
答案 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,因为您已经在不同的列表上进行了迭代。