You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 17:17:05