根本原因是页面状态判断逻辑缺失:初始list=[]立刻触发空状态渲染,接口返回后才切列表,造成视觉断层;需用isLoading标识加载中态,v-if优先判断loading,再判数据,且key必须稳定唯一、图片需预留高度或监听load。

为什么异步请求会引发闪烁
根本原因不是网络慢,而是页面状态判断逻辑缺失:初始 list = [] 立刻满足 list.length === 0,导致空状态提前渲染;等接口返回后才切到列表——中间这几百毫秒就是用户看到的“闪一下”。小程序双线程通信+WebView渲染延迟会放大这个视觉断层。
v-if 判断必须加 loading 状态
不能只靠数据长度判断显隐,必须引入独立的加载标识。否则哪怕数据秒回,v-if 也会因响应式触发时机问题造成短暂空白。
-
isLoading初始化为true,在请求发起前就设为true(别等到onMounted里再赋值) - 模板中优先判断
v-if="isLoading",其次才是v-else-if="list.length === 0" - 务必在
try/catch/finally的finally块里把isLoading设为false,避免异常时 loading 永久挂起
列表项 key 必须稳定且唯一
如果 key 是 :key="index" 或临时生成的随机数,Vue 无法复用节点,每次更新都会销毁重建 DOM,直接引发抖动或白屏。
- 用后端返回的唯一字段,如
:key="item.id"(严禁用Math.random()或Date.now()) - 确保接口返回的
id在整个生命周期内不变,尤其注意分页场景下不要出现重复 id - 若数据结构无天然 id,可在请求后用
map注入带 hash 的唯一 key,但不如后端给更可靠
图片加载必须预留高度或监听 @load
列表里 高度为 0 时占位塌陷,新数据插入后所有行重排,视觉上就是整列“弹跳”。
- 全局样式强制设高:
image { height: 200rpx; }(比 aspect-ratio 兼容性更好) - 若需动态高度,用
@load+v-if控制显隐: - 禁用
v-show替代v-if,它不移除 DOM,仍会参与初始布局计算
关键点在于:闪烁不是渲染引擎的问题,是状态管理漏掉了“加载中”这一中间态。很多开发者卡在“数据有了就该显示”,却忘了用户感知的是过程,不是结果。











