VueJS中Vuetify Autocomplete结合Axios的查询与显示问题求助
Vuetify 3 V-Autocomplete 数据显示与值绑定问题解决
问题背景
使用Vuetify 3的V-Autocomplete组件展示人员姓名列表,初始阶段无法执行查询获取数据;调整后已能从接口拿到包含id和name的JSON数据,但组件无法正确显示name字段,且需要实现选中选项时将id绑定到v-model。
初始问题代码(app.js)
import './bootstrap'; import { createApp, h } from 'vue' import { createInertiaApp } from '@inertiajs/vue3' import 'vuetify/styles' import { createVuetify } from 'vuetify' import * as components from 'vuetify/components' import * as directives from 'vuetify/directives' import { aliases, mdi } from 'vuetify/iconsets/mdi' const vuetify = createVuetify({ components, directives, }) const myCustomLightTheme = { dark: false, colors: { background: '#CCCCCC', surface: '#FFFFFF', primary: '#6200EE', 'primary-darken-1': '#3700B3', secondary: '#03DAC6', 'secondary-darken-1': '#018786', error: '#B00020', info: '#2196F3', success: '#4CAF50', warning: '#FB8C00', }, } export default createVuetify({ theme: { defaultTheme: 'myCustomLightTheme', themes: { myCustomLightTheme, }, }, }) createInertiaApp({ resolve: name => { const pages = import.meta.glob('./Pages/**/*.vue', { eager: true }) return pages[`./Pages/${name}.vue`] }, setup({ el, App, props, plugin }) { createApp({ render: () => h(App, props) }) .use(plugin) .use(vuetify) .mount(el) }, })
初始问题代码(Component.vue)
<script setup> import {Head, useForm} from '@inertiajs/vue3'; import { Link } from '@inertiajs/vue3'; const props = defineProps(['curso','form','submit']); </script> <template> <v-container> <v-form @submit.prevent="submit"> <v-row> <v-col cols="6"> <v-autocomplete v-model="selectAcc" v-model:search="searchAcc" :loading="loadingAcc" :items="itemsAcc" menu-icon="" density="compact" variant="outlined" hide-no-data hide-details label="Coordenador do Curso" ></v-autocomplete> </v-col> </v-row> </v-form> </v-container> </template> <script> export default { data () { return { loadingAcc: false, itemsAcc: [], searchAcc: null, selectAcc: null, pessoas: [], } }, watch: { searchAcc(val) { val && val !== this.selectAcc && this.querySelections(val) }, }, methods: { querySelections (p) { this.loadingAcc = true this.pessoas = []; setTimeout(() => { axios.get('/api/search',{params: {nome: p}}).then(response => { response.data.forEach((pessoa)=>{ this.itemsAcc = this.pessoas.filter(e => { return (e || '').toLowerCase().indexOf((p || '').toLowerCase()) > -1 }) }) }) this.loading = false }, 500) }, }, } </script>
更新后的问题代码(Component.vue)
<template> <v-autocomplete v-model="selectAcc" v-model:search="searchAcc" :loading="loadingAcc" label="Coordenador do Curso" menu-icon="" :items="itemsAcc" item-value="itemsAcc.id" item-text="itemsAcc.value" hide-no-data hide-details variant="outlined" density="compact"> </v-autocomplete> </template> <script> export default { data () { loadingAcc: false, itemsAcc: [], searchAcc: null, selectAcc: null, }, watch: { searchAcc (val) { val && val !== this.selectAcc && this.querySelections(val) }, }, methods: { querySelections (v) { this.loadingAcc = true this.itemsAcc = []; axios.get('/api/search',{params: {nome: v}}).then(response => { response.data.forEach((pessoa)=>{ this.itemsAcc.push(pessoa); //this.itemsAcc = this.pessoas; }) }) this.loadingAcc = false }, }, } </script>
解决方案
1. 修正item-text与item-value配置
item-text和item-value需直接指定数据对象中的字段名,而非数组加字段。你的接口返回对象包含id和name,因此修改如下:
<v-autocomplete v-model="selectAcc" v-model:search="searchAcc" :loading="loadingAcc" label="Coordenador do Curso" menu-icon="" :items="itemsAcc" item-value="id" <!-- 直接绑定id字段 --> item-text="name" <!-- 直接绑定name字段作为显示文本 --> hide-no-data hide-details variant="outlined" density="compact"> </v-autocomplete>
2. 修复异步请求的加载状态逻辑
当前代码中loadingAcc在请求发送后立即设为false,会导致加载状态不生效,需将状态更新放到请求回调内:
querySelections (v) { this.loadingAcc = true this.itemsAcc = []; axios.get('/api/search',{params: {nome: v}}) .then(response => { this.itemsAcc = response.data; // 直接赋值接口返回的数组,无需遍历push this.loadingAcc = false }) .catch(() => { this.loadingAcc = false // 异常场景也要重置加载状态 }) }
3. 修正初始代码的数据处理逻辑
初始代码中querySelections方法内,this.pessoas是空数组,过滤后赋值给itemsAcc自然无数据;同时setTimeout包裹请求无必要,直接发起异步请求即可。
4. 统一组件写法(可选优化)
将<script setup>与普通<script>合并,保持代码风格一致:
<script setup> import { ref, watch } from 'vue'; import { Head, useForm } from '@inertiajs/vue3'; import { Link } from '@inertiajs/vue3'; const props = defineProps(['curso','form','submit']); const loadingAcc = ref(false); const itemsAcc = ref([]); const searchAcc = ref(null); const selectAcc = ref(null); watch(searchAcc, (val) => { if (val && val !== selectAcc.value) { querySelections(val); } }); const querySelections = (v) => { loadingAcc.value = true; itemsAcc.value = []; axios.get('/api/search', { params: { nome: v } }) .then(response => { itemsAcc.value = response.data; loadingAcc.value = false; }) .catch(() => { loadingAcc.value = false; }); }; </script> <template> <v-container> <v-form @submit.prevent="submit"> <v-row> <v-col cols="6"> <v-autocomplete v-model="selectAcc" v-model:search="searchAcc" :loading="loadingAcc" :items="itemsAcc" menu-icon="" density="compact" variant="outlined" hide-no-data hide-details label="Coordenador do Curso" item-value="id" item-text="name" ></v-autocomplete> </v-col> </v-row> </v-form> </v-container> </template>
关键说明
item-text:指定下拉列表显示的文本字段,对应数据对象的name属性item-value:指定选中后绑定到v-model的值,对应数据对象的id属性- 异步请求必须在回调内更新加载状态,避免UI状态异常
- 直接将接口返回的数组赋值给
itemsAcc即可,无需额外遍历push
内容的提问来源于stack exchange,提问作者Dionísio Pereira Júnior
相关产品推荐
相关产品推荐

