勇敢的心_
勇敢的心_
  • 发布:2026-01-18 10:17
  • 更新:2026-01-18 10:17
  • 阅读:11

【报Bug】用雪花ID当作v-for的key,导致组件内容错乱

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: 11

HBuilderX类型: 正式

HBuilderX版本号: 4.87

手机系统: Android

手机系统版本号: Android 12

手机厂商: 华为

手机机型: nova 5 Pro

页面类型: vue

vue版本: vue2

打包方式: 云端

项目创建方式: HBuilderX

示例代码:
<view v-for="(item, index) in chatList" :key="item.msgId"> <view :style="{flexDirection:item.isSelf?'row-reverse':'row'}" class="flex padding-sm"> <view :class="[item.isSelf?'padding-left-sm':'padding-right-sm']"> <image v-if="item.isSelf" :src="user?user.avatar:''" class="avatar"></image> <image v-else :src="teacher?teacher.avatar:''" class="avatar"></image> </view> <view class="flex-sub"> <view class="flex" style="padding-bottom:4px;"

style="{flexDirection: item.isSelf ? 'row-reverse' : 'row'}"> <text v-if="item.isSelf" class="text-sm text-gray">{{user.name}}</text>
<text v-else class="text-sm text-gray">{{teacher?teacher.nickname:''}}</text>
<text class="text-sm text-gray">({{formatTimestamp(item.clientTime)}})</text>
</view>
<view :style="{flexDirection:item.isSelf?'row':'row-reverse'}" class="flex align-end justify-end">

                    <view class="margin-right-sm">  
                        <view v-if="item.isSelf" class="text-right" style="width:36px;">  
                            <text class="text-sm text-gray">{{item.isRead?'已读':'未读'}}</text>  
                        </view>  
                    </view>  
                    <view v-if="item.msgType=='text'" @longpress="chatLongpress(item)">  
                        <!-- <view class="bg-red">{{item.msgBody}}</view> -->  
                        <view class="bg-yellow">{{item.msgId}}</view>  
                        <view class="bg-red">{{item.msgBody}}</view>  
                        <text-item :text="item.msgBody" :isSelf="item.isSelf"></text-item>  
                    </view>  
                    <view v-else-if="item.msgType=='photo'" @longpress="chatLongpress(item)">  
                        <image-item :image="item.msgBody"></image-item>  
                    </view>  
                    <view v-else-if="item.msgType=='voice'" @longpress="chatLongpress(item)">  
                        <voice-item :isSelf="item.isSelf" :voicePlayState="(playingVoiceMsgId===item.msgId && voicePlayState===1)?1:0" @click.native="playVoice(item)" :voice="item.msgBody"></voice-item>  
                    </view>  
                    <view v-else-if="item.msgType=='video'" @longpress="chatLongpress(item)">  
                        <video-item :video="item.msgBody"></video-item>  
                    </view>  
                    <view v-else-if="item.msgType=='ai'">  
                        <ai-item :text="item.msgBody" :itemMaxWidth="itemMaxWidth" :isSelf="item.isSelf"></ai-item>  
                    </view>  
                </view>  
            </view>  
            <!-- <view :class="[item.isSelf?'padding-right-sm':'padding-left-sm']">  
                <view class="avatar"></view>  
            </view> -->  
        </view>  

    </view>  
    <view v-if="issue.issue_status==6">  
        <view class="padding padding-top">  
            <view class="text-center">  
                <text class="text-df text-grey">工单已结束</text>  
            </view>  
        </view>  
    </view>  

    <view slot="bottom" class="bg-white">  
        <view v-if="roomId==0">  
            <view class="padding bg-gray">  
                <view class="text-df text-bold text-center text-black">正在分配老师,请稍后...</view>  
            </view>  
        </view>  
        <view v-else-if="issue.issue_status!=6" class="flex flex-row align-center padding-sm">  
            <image @tap="toolShow" src="@/static/chat/add.png" class="block" style="width:30px;height:30px;"></image>  
            <view class="flex-sub flex flex-row align-center bg-light-blue margin-lr-sm padding-xs radius">  
                <view>  
                    <input ref="chatInput" v-model="content" placeholder="请输入内容(最多120字)" maxlength="120" :adjust-position="true" confirm-type="send" style="height:30px;line-height:1rem;" class="text-df text-black flex-sub padding-left-xs">  
                </view>  

                <button @tap="sendText" v-if="content.length>0" style="height:30px;width:60px;border:none;border-radius:6px;background-image:linear-gradient(to right, #4e8eff, #5eacff);">  
                    <text style="color:#ffffff;" class="text-sm text-bold">发 送</text>  
                </button>  
            </view>  
            <image @tap.stop="voiceShow" src="/static/chat/voice.png" class="block" style="width:30px;height:30px;"></image>  
        </view>  
        <tool @upload="uploadMedia" v-if="toolModel" height="200"></tool>  
        <voice @stop="voiceStop" v-if="voiceModel" height="200"></voice>  
    </view>

操作步骤:
<view v-for="(item, index) in chatList" :key="item.msgId">

预期结果:

1

实际结果:

1

bug描述:

用雪花ID当作v-for的key,导致组件内容错乱

2026-01-18 10:17 负责人:无 分享
已邀请:
Ask小助手

Ask小助手 - Ask社区AI助手

该bug反馈内容不完整:描述缺乏具体错乱现象细节,预期/实际结果仅写"1"无意义,复现步骤过于简略仅一行代码。但分类信息完整(Android 12/HBuilderX 4.87/Vue2)。

经核查知识库,该问题成立。Android平台存在组件复用机制缺陷:App-Android平台 修复 组件 list-item 子组件复用后 event 事件可能触发异常。当使用雪花ID(非线性唯一值)作为v-for的key时,uni-app的虚拟列表优化会错误复用组件实例,导致状态错乱。尤其在聊天列表这种动态增删场景下,问题更易复现。

建议解决方案:

  1. 优先升级至最新HBuilderX版本(当前4.87可能未包含完整修复)
  2. 改用连续自增ID作为key(避免雪花ID的非连续性干扰复用机制)
  3. 对于长列表改用list-view组件(文档说明),其专为高性能列表设计且已修复复用问题
  4. 若必须用雪花ID,可添加唯一前缀(如key="chat_"+item.msgId)增强稳定性

注意:这不是Vue基础概念问题,而是uni-app Android平台特有的组件复用实现缺陷。鸿蒙平台需单独验证,但本例属Android问题范畴。

内容为 AI 生成,仅供参考

要回复问题请先登录注册