Vuetify Autocomplete组件中如何过滤重复模板项
解决Autocomplete组件的重复项与批量选中问题
咱们先拆解你遇到的两个问题,一步步给出具体的解决方案:
一、去除下拉列表的重复项
你当前直接把原始数组传给所有Autocomplete,自然会出现重复值——因为原始数组里的多个对象可能在目标属性上有相同的值。不要在模板里做过滤,应该在传给组件前就处理好数据,这更符合Vue的数据流逻辑,也更高效。
实现思路
针对每个Autocomplete的label,先从原始数组中提取对应属性的所有值,通过Set快速去重,再整理成组件需要的结构(如果需要保留完整对象,就取每个唯一值对应的第一个对象实例)。
具体代码示例
假设你的原始数据数组叫rawItems,可以在组件的计算属性里为每个label生成去重后的选项:
computed: { getFilteredItems() { return (targetLabel) => { const propKey = targetLabel.replace('filters.', '') // 用Set去重属性值,再转回数组 const uniqueValues = [...new Set(this.rawItems.map(item => item.properties[propKey]))] // 映射回完整的item对象(取每个唯一值对应的第一个对象) return uniqueValues.map(value => { return this.rawItems.find(item => item.properties[propKey] === value) }) } } }
然后在模板里给每个Autocomplete传处理后的数组:
<Autocomplete :items="getFilteredItems(label)" :label="label" <!-- 其他props --> > <!-- 你的自定义item模板 --> </Autocomplete>
这样每个Autocomplete拿到的都是去重后的选项,下拉列表就不会有重复项了。
二、解决选中一项全选的问题
这个问题的核心是所有复选框共享了同一个选中状态判断逻辑——你的isChecked(item)方法没有区分不同Autocomplete组件的选中项,也没有为每个组件维护独立的选中集合。
实现思路
为每个Autocomplete组件维护独立的选中状态,比如用一个对象存储,key是组件的label,value是该组件下选中的项集合(用Set操作更高效)。
具体代码示例
- 在data中初始化选中状态存储:
data() { return { selectedItems: {} // 结构:{ [label]: Set } } }
- 修改选中判断和切换方法,加入label区分:
methods: { isChecked(item, label) { const propKey = label.replace('filters.', '') const targetValue = item.properties[propKey] // 若当前label无选中集合,初始化一个Set if (!this.selectedItems[label]) { this.selectedItems[label] = new Set() } return this.selectedItems[label].has(targetValue) }, toggleCheck(item, label) { const propKey = label.replace('filters.', '') const targetValue = item.properties[propKey] if (!this.selectedItems[label]) { this.selectedItems[label] = new Set() } // 切换选中状态 this.selectedItems[label].has(targetValue) ? this.selectedItems[label].delete(targetValue) : this.selectedItems[label].add(targetValue) } }
- 更新模板,给方法传入label参数:
<template #item="{ item }"> <v-list-item-action> <v-checkbox :input-value="isChecked(item, label)" @change="toggleCheck(item, label)" ></v-checkbox> </v-list-item-action> <v-list-item-content @click="toggleCheck(item, label)"> <span class="pr-2"> {{ item.properties[label.replace('filters.', '')] }} </span> </v-list-item-content> </template>
这样每个Autocomplete的选中状态都是独立的,点击一个选项只会影响当前组件内的选中状态。
关于你的实现方式的小建议
你的自定义模板思路是没问题的,但数据处理尽量放在逻辑层(computed/methods)而非模板中,模板只负责渲染逻辑层处理好的数据,这样代码更清晰,也更容易维护调试。
内容的提问来源于stack exchange,提问作者Jérôme BORGA
相关产品推荐
相关产品推荐

