uni-app 局部刷新需手动控制状态与dom边界:scroll-view自定义下拉刷新最常用,需设scroll-y、显式高度及refresher属性;单条目刷新用loadingmap隔离状态;数据更新须用$set或整体替换;返回页面按需刷新,避免重复请求与内存泄漏。

局部刷新在 uni-app 里没有“开箱即用”的 API,onPullDownRefresh 是页面级的,uni.reload() 和 uni.reLaunch() 是全量刷新——真要只刷某一块内容,必须自己控制状态、数据和 DOM 更新边界。
scroll-view 自定义下拉刷新(最常用)
这是目前兼容性最好、行为最可控的局部下拉方案,本质是用 scroll-view 替代原生页面滚动,并接管手势逻辑。
-
scroll-view必须设置scroll-y="true"和显式高度(如height: 500rpx),否则@refresherpulling等事件不触发 - 启用内置 refresher 时,
:refresher-enabled="true"和:refresher-triggered="triggered"缺一不可,且triggered必须手动管理:下拉开始设true,刷新完成或中断后必须设回false - iOS 下
scroll-view默认开启bounce,容易误触发下拉,建议加bounce="false" - H5 端对
refresher-threshold响应不稳定,阈值建议设高些(如120),并配合@refresherrefresh中调用接口后立即重置triggered = false
<scroll-view scroll-y :refresher-enabled="true" :refresher-triggered="triggered" :refresher-threshold="100" :style="{ height: '500rpx' }"><!-- 列表内容 --></scroll-view>
v-if 控制单条目 loading + 精准更新数据
点击某个按钮只刷新对应卡片/列表项?关键不是“刷新”,而是“隔离状态”和“响应式穿透”。
- 别用全局
loading变量,用loadingMap对象,以唯一 ID(如item.id)为 key:loadingMap[item.id] = true - 模板中用
v-if="loadingMap[item.id]"控制 loading 插槽,不用v-show——后者残留 DOM 容易遮挡交互 - 修改数组中某一项字段时,直接赋值(如
this.list[0].status = 'done')在小程序端大概率失效,必须用this.$set(this.list[0], 'status', 'done') - 若用 Vue 3 的
ref声明 list,更新时不能只改属性,得整体替换:list.value = list.value.map((item, i) => i === index ? { ...item, status: 'done' } : item)
返回页面时按需刷新(非自动全量)
用户从详情页编辑后返回列表页,该不该刷新?不是每次 onShow 都要拉数据,得区分场景。
- 把请求逻辑移到
onShow是基础,但首次进入时onLoad已拉过,可用标志位(如this.dataLoaded = true)避免重复请求 - 分页类页面在
onShow中必须重置page = 1和list = [],否则下拉加载会拼错数据 - 需要精准控制时机时,用事件总线:
uni.$on('refreshList')在列表页监听,详情页保存成功后uni.$emit('refreshList');记得在onUnload里uni.$off,否则内存泄漏 - 禁用原生导航栏返回时(
navigationStyle: custom),务必在自定义按钮里调uni.navigateBack(),否则onShow不触发
真正难的不是写几行代码,而是判断“这一块到底要不要刷新”——loading 状态是否隔离、数据更新是否穿透、返回时机是否可信。这些地方一松懈,局部刷新就变成全局卡顿或者视图失步。











