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

Vue/Nuxt动态渲染Select选项异常:搜索结果无法实时更新

问题分析与解决方案

你的核心问题是Vue 2无法检测数组通过索引直接赋值的操作,导致results[matchId]更新后视图不触发重渲染;同时单个防抖定时器会导致多个输入框互相干扰,进一步加剧了结果显示异常的问题。

修复方案

1. 替换数组为对象存储状态

Vue 2的响应式系统对数组的索引赋值(如this.results[matchId] = ...)无感知,改用对象存储results、queries、selectInputs,以match.id为键,既能解决响应式问题,也更符合按ID独立存储的逻辑。

2. 为每个输入框维护独立防抖定时器

原代码中单个定时器会导致多个输入框的防抖逻辑互相干扰,改为对象存储每个matchId对应的定时器,确保每个输入框的搜索防抖独立运行。

3. 确保响应式更新

首次给对象新增属性时,使用Vue.set将属性纳入响应式系统,后续更新可直接赋值。

修改后的完整代码

<template>
    <div>
        <tbody v-for="match in matchData.results" :key="match.id">
            <tr class="border-b">
                <td class="py-2 px-6 max-w-xs">
                    <div class="relative">
                        <input v-model="queries[match.id]" @input="debounceSearchMatch(match.id)" type="text" class="block w-full rounded-md border border-gray-200 py-1 px-4 text-sm shadow-sm outline-none" placeholder="Search" />
                        <div class="pointer-events-none absolute inset-y-0 right-0 z-20 flex items-center pr-2">
                            <font-awesome-icon icon="fa-solid fa-magnifying-glass" class="fa-sm text-navy-100" />
                        </div>
                    </div>
                    <div class="relative w-11/12">
                        <select v-model="selectInputs[match.id]" class="block w-full rounded-md border border-gray-200 py-1 pl-6 pr-11 text-sm shadow-sm outline-none text-gray-500">
                            <option :value="result.id" v-for="result in results[match.id] || []" :key="result.id">{{result.home.name}} - {{ result.away.name }}</option>
                        </select>
                    </div>
                </td>
            </tr>
        </tbody>
    </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
    props: ["data"],
    data() {
        return {
            matchData: this.$props.data,
            debounceTimeouts: {}, // 按matchId存储独立定时器
            selectInputs: {},
            results: {},
            queries: {}
        };
    },
    methods: {
        debounceSearchMatch(matchId: number) {
            // 清除当前matchId的旧定时器
            if (this.debounceTimeouts[matchId]) {
                clearTimeout(this.debounceTimeouts[matchId]);
            }
            // 设置新定时器
            this.debounceTimeouts[matchId] = setTimeout(() => {
                this.searchMatch(matchId);
            }, 500);
        },
        async searchMatch(matchId: number) {
            const query = this.queries[matchId] || '';
            const response = await this.$axios.get(`/matches?query=${query}`);
            // 首次赋值用Vue.set确保响应式,后续可直接赋值
            Vue.set(this.results, matchId, response.data.results);
        }
    },
})
</script>

关键修改说明

  • 移除了全局results变量,避免多组件实例共享状态的问题
  • 将数组类型的状态全部改为对象,通过match.id作为键实现独立存储
  • 每个输入框拥有独立的防抖定时器,不会互相干扰
  • 使用Vue.set处理对象新增属性的响应式注册,确保视图能正确更新

内容的提问来源于stack exchange,提问作者Sander Bakker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 01:10:28