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

vue-virtual-scroller中DynamicScroller嵌套展开面板异常问题

解决DynamicScroller中Vuetify展开面板状态错乱问题

这个问题的核心是虚拟滚动组件会复用DOM元素,如果展开状态存在ToDoItem组件内部,滚动或操作时组件复用时就会把状态带到其他item上,导致展开面板串开。加上你之前可能没把key绑定到正确的位置,所以问题没解决。

直接按以下步骤修改:

  1. 给每个ToDo项添加独立的展开状态
    在你的toDos数组的每个对象里新增isExpanded字段,用来单独控制每个项的展开状态,比如:

    // 初始化或获取数据时处理
    this.toDos = this.toDos.map(todo => ({
      ...todo,
      isExpanded: false
    }))
    
  2. 正确绑定key到DynamicScrollerItem和ToDoItem
    虚拟滚动里必须用item的唯一标识(比如id)作为key,不能用index,因为index会随着滚动复用变化。修改模板:

    <DynamicScroller :items="toDos" :min-item-size="190" class="scroller pr-3 fill-height">
        <template v-slot="{ item, index, active }">
            <DynamicScrollerItem 
                :item="item" 
                :active="active" 
                :data-index="index"
                :key="item.id" <!-- 绑定item的唯一标识 -->
            >
                <ToDoItem 
                    :toDo="item" 
                    :is-expanded="item.isExpanded" <!-- 传递展开状态 -->
                    @updateToDo="updateToDo"
                    @toggle-expand="toggleExpand(item)" <!-- 监听展开切换事件 -->
                    :key="item.id" <!-- ToDoItem也绑定唯一key -->
                />
            </DynamicScrollerItem>
        </template>
    </DynamicScroller>
    
  3. 修改ToDoItem组件,接收外部状态并触发事件
    把ToDoItem内部的展开状态改成由父组件传入,点击展开按钮时触发事件通知父组件更新:

    <!-- ToDoItem.vue -->
    <template>
      <v-expansion-panel :value="isExpanded">
        <v-expansion-panel-header @click="$emit('toggle-expand')">
          {{ toDo.title }}
        </v-expansion-panel-header>
        <v-expansion-panel-content>
          <!-- 你的面板内容 -->
        </v-expansion-panel-content>
      </v-expansion-panel>
    </template>
    
    <script>
    export default {
      props: {
        toDo: Object,
        isExpanded: Boolean
      },
      emits: ['toggle-expand', 'updateToDo']
      // 其他原有逻辑...
    }
    </script>
    
  4. 父组件实现toggleExpand方法
    在父组件里添加方法来切换对应item的展开状态:

    methods: {
      toggleExpand(item) {
        // 确保响应式更新,如果直接修改不生效,改用this.$set
        this.$set(item, 'isExpanded', !item.isExpanded)
      },
      updateToDo(updatedTodo) {
        // 你的原有更新逻辑
      }
    }
    

这样修改后,每个ToDo项的展开状态都绑定到自身的数据字段,不会因为虚拟滚动的组件复用而串开,同时正确的key也能帮助Vue识别每个组件的唯一性,避免复用错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 23:58:07