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

使用Firestore数据时Vuetify item-group选中项异常变更求助

解决方案

问题根源

  1. 错误的列表key:使用index作为v-list-item的:key,当Firestore数据排序更新后,同一位置的index对应新的item,Vue的diff算法会复用原组件,导致选中状态错位。
  2. 选中状态未绑定固定标识:之前的实现依赖列表位置或临时渲染对象,没有将选中状态与Firestore文档唯一的id绑定。

修复步骤

1. 替换列表项的key为文档ID

将v-list-item的:key="index"改为:key="item.id",确保每个列表项的标识是唯一且不变的,Vue能正确跟踪每个组件实例。

2. 维护选中的ID而非位置

在data中存储选中的文档ID(单选存单个ID,多选存ID数组),而不是索引或对象,避免数据更新时丢失关联。

3. 修复计算属性的getter

让listSelection的getter返回当前选中的ID,确保v-list-item-group的v-model正确绑定到固定ID,setter保持原逻辑(向父组件传递选中的完整对象)。

修改后的完整代码

<template>
  <div>
    <v-container fluid>
      <v-list>
        <v-list-item-group v-model="listSelection">
          <!-- 用item.id作为唯一key -->
          <v-list-item v-for="item in online" :key="item.id" :value="item.id">
            {{ item }}
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-container>
  </div>
</template>

<script>
import db from "@/components/fbInit";

export default {
  props: {
    // 父组件传入的选中对象(可选,若用v-model绑定)
    value: {
      type: Object,
      default: null
    }
  },

  data() {
    return {
      online: [],
      // 存储选中的文档ID,单选用null,多选用[]
      selectedId: null
    };
  },

  firestore: {
    online: db.collection('item').orderBy('rank', 'asc')
  },

  computed: {
    listSelection: {
      // 返回当前选中的ID,与父组件传入的value同步
      get() {
        return this.value?.id || this.selectedId;
      },
      set(newVal) {
        this.selectedId = newVal;
        // 向父组件传递选中的完整对象
        const selectedItem = this.online.find(item => item.id === newVal);
        this.$emit('input', selectedItem);
      }
    }
  }
};
</script>

额外说明

  • 如果是多选场景,只需将selectedId改为数组selectedIds: [],并确保v-list-item-group的multiple属性设为true,同时调整getter和setter的逻辑处理数组即可。
  • 由于绑定了固定的文档ID,即使Firestore数据排序或更新,选中状态会始终关联到对应ID的卡片,不会出现错位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 14:10:30