如何使用Vuetify的v-select实现下拉条目展示与输入搜索功能?
问题
我希望在Vuetify的v-select组件中同时实现两个功能:
- 以折叠/展开的形式展示选项条目(比如分组树形结构)
- 支持在输入框中输入文本,对选项进行搜索过滤
请问Vuetify有没有现成的prop可以直接实现,或者有什么实用的实现技巧?
当前使用的v-select代码如下:
<v-select v-model="searchParams.importApples" label="Importapples" :items="importApplesItems" :menu-props="{ bottom: true, offsetY: true }" item-text="label" item-value="value" filterable clearable outlined dense />
解决方案
一、原生分组折叠+搜索(适合简单分组场景)
Vuetify的v-select支持通过分组数据结构结合group-by prop实现折叠分组,同时保留filterable的搜索功能。
- 调整数据结构,给每个选项添加分组标识字段(比如
group):
const importApplesItems = [ { label: '红富士', value: 'red-fuji', group: '国产苹果' }, { label: '花牛', value: 'huaniu', group: '国产苹果' }, { label: '蛇果', value: 'red-delicious', group: '进口苹果' }, { label: '青苹果', value: 'granny-smith', group: '进口苹果' } ]
- 修改
v-select组件,添加group-by和group-filterprop(可选,控制分组是否随搜索过滤):
<v-select v-model="searchParams.importApples" label="Importapples" :items="importApplesItems" :menu-props="{ bottom: true, offsetY: true }" item-text="label" item-value="value" group-by="group" group-filter="label" // 搜索时过滤分组下的选项,空分组自动隐藏 filterable clearable outlined dense />
- 效果:选项按
group字段自动分组,每个分组默认可折叠/展开,输入框的搜索会实时过滤分组内的选项,无匹配项的分组会自动隐藏。
二、自定义树形折叠+搜索(适合多级树形结构)
如果需要更复杂的多级树形折叠(父节点嵌套子节点),可以通过v-select的自定义菜单模板结合v-treeview实现,同时绑定搜索逻辑:
- 准备树形结构的数据:
const importApplesItems = [ { id: 'domestic', name: '国产苹果', children: [ { id: 'red-fuji', name: '红富士' }, { id: 'huaniu', name: '花牛' } ] }, { id: 'imported', name: '进口苹果', children: [ { id: 'red-delicious', name: '蛇果' }, { id: 'granny-smith', name: '青苹果' } ] } ]
- 修改
v-select组件,自定义菜单内容并嵌入v-treeview:
<v-select v-model="searchParams.importApples" label="Importapples" :menu-props="{ bottom: true, offsetY: true, maxHeight: 400 }" clearable outlined dense @update:search-input="handleSearch" // 监听输入框的搜索文本 > <template v-slot:menu="{ props }"> <v-treeview v-bind="props" :items="filteredItems" item-key="id" item-text="name" open-on-click activatable selectable @update:active="(active) => searchParams.importApples = active[0]" /> </template> </v-select>
- 实现搜索过滤逻辑:
import { ref, computed } from 'vue' const searchParams = ref({ importApples: '' }) const importApplesItems = ref([/* 树形数据 */]) const searchText = ref('') const filteredItems = computed(() => { if (!searchText.value) return importApplesItems.value // 递归过滤树形数据,保留包含搜索文本的节点及其父节点 const filterTree = (items) => { return items.map(item => { const filteredChildren = item.children ? filterTree(item.children) : [] const matches = item.name.includes(searchText.value) || filteredChildren.length > 0 return matches ? { ...item, children: filteredChildren } : null }).filter(Boolean) } return filterTree(importApplesItems.value) }) const handleSearch = (val) => { searchText.value = val }
- 效果:菜单内展示可折叠的树形结构,输入框文本会实时过滤树形节点,匹配的节点及其父节点会被保留显示。
关键注意点
- 第一种方案适合简单一级分组,无需额外代码,完全依赖Vuetify原生prop实现;
- 第二种方案适合多级树形结构,需要自定义菜单和过滤逻辑,但灵活性更高;
- 两种方案都保留了
v-select的核心交互(如v-model绑定、清空按钮等)。
内容的提问来源于stack exchange,提问作者Saturday Sun
相关产品推荐
相关产品推荐

