Nuxt项目中Vuetify Autocomplete下拉框不实时显示搜索结果问题
问题原因
导致输入后下拉框不实时展示的核心原因有2个:
- Vuetify Autocomplete默认开启了前端过滤逻辑,你从后端拿到匹配结果后,组件会用当前输入的字符再做一次前端过滤,很容易出现误判无匹配结果、隐藏下拉菜单的情况,只有重新聚焦时才会重新计算展示。
- 你监听搜索词的watch中存在无效逻辑,且数组更新方式可能触发响应式更新延迟。
修复方案
第一步:修改模板代码
给v-autocomplete组件添加no-filter属性,禁用前端默认过滤,可选添加menu-props保证菜单正常弹出:
<v-autocomplete v-model="pickupairport" name="pickupairport" :items="airports" :loading="isLoading" :search-input.sync="aptsearch" chips clearable hide-details hide-selected label="Search for a airport..." solo no-filter :menu-props="{ openOnClick: true, closeOnContentClick: false }" > <!-- 原有slot代码保持不变 --> <template v-slot:no-data> <v-list-item> <v-list-item-title> Search for your favorite <strong>Destinations</strong> </v-list-item-title> </v-list-item> </template> <template v-slot:selection="{ attr, on, item, selected }"> <v-chip v-bind="attr" :input-value="selected" color="blue-grey" class="white--text" v-on="on"> <v-icon left> mdi-bitcoin </v-icon> <span v-text="item.name"></span> </v-chip> </template> <template v-slot:item="{ item }"> <v-list-item-avatar color="indigo" class="text-h5 font-weight-light white--text"> {{ item.name.charAt(0) }} </v-list-item-avatar> <v-list-item-content> <v-list-item-title v-text="item.name"></v-list-item-title> <v-list-item-subtitle>{{item.cityName}}, {{item.countryName}}</v-list-item-subtitle> </v-list-item-content> <v-list-item-action> <v-icon>fa-airports</v-icon> </v-list-item-action> </template> </v-autocomplete>
第二步:修改script逻辑
删除watch中无效的判断逻辑,优化数组赋值方式,可选添加防抖避免频繁请求:
export default { data() { return { aptsearch: null, items: [], model: null, tab: null, pickupairport: '', airports: [], isLoading: false, uuid: this.$uuid.v4(), searchTimer: null // 新增防抖定时器变量 } }, watch: { model(val) { if (val != null) this.tab = 0 else this.tab = null }, aptsearch(val) { // 防抖逻辑:300ms内重复输入不发请求 if (this.searchTimer) clearTimeout(this.searchTimer) // 输入为空时直接清空结果不发请求 if (!val || val.trim().length === 0) { this.airports = [] return } this.searchTimer = setTimeout(() => { this.isLoading = true // 原有请求逻辑 fetch(`${process.env.EXPRESS_API_URL}/airports/find`, { method: "post", headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ aptsearchkey: val }) }) .then(response => response.json()) .then((data) => { // 直接赋值数组,触发响应式更新 this.airports = data }) .catch(err => { console.log(err) }) .finally(() => (this.isLoading = false)) }, 300) }, } }
改动说明
no-filter:禁用组件默认的前端过滤,完全使用后端返回的匹配结果展示,避免过滤逻辑冲突导致下拉隐藏- 防抖逻辑:避免每次输入都触发API请求,减少后端压力,也避免频繁更新数组导致组件渲染异常
- 直接赋值数组:比循环push的响应式触发更稳定,保证组件可以立即检测到
airports数组的变化,自动弹出下拉菜单
内容的提问来源于stack exchange,提问作者imthegrv
相关产品推荐
相关产品推荐

