在小程序里做下拉刷新,开启页面级刷新只需要在 JSON 配置里加上 enablePullDownRefresh,但很多项目在设计稿中要求 loading 图标、背景色、文字颜色全部与品牌风格统一。原生能力只能覆盖其中一部分,想做到完全自定义就必须理解配置边界,并换成 <scroll-view> 的 refresher 方案。下面先把原生配置能改哪些样式理清楚,再给出可落地的自定义实现。

一、原生下拉刷新的样式边界
页面级下拉刷新依靠 JSON 文件中的三个配置项来调整基础外观。enablePullDownRefresh 负责开启下拉刷新,backgroundColor 指定刷新区域的背景色,backgroundTextStyle 控制刷新文字和系统 loading 图标的明暗,可选值只有 dark 和 light。也就是说,原生方案无法把 loading 图标替换成自定义动画,也不能把提示文字设置为任意颜色,只能根据背景深浅选择黑或白。
在单个页面配置时,可以直接在页面对应的 JSON 文件中写入:
{
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark",
"backgroundColor": "#f5f5f5"
}
如果希望整个小程序所有页面都启用下拉刷新,可以在 app.json 的 window 字段中进行全局设置。例如深色页面想使用浅色 loading 文字,可以这样写:
{
"window": {
"enablePullDownRefresh": true,
"backgroundTextStyle": "light",
"backgroundColor": "#1f1f1f"
}
}
这里有一个容易踩中的点:backgroundTextStyle 并不是任意 CSS 颜色值,传入 #ff6600 这样的写法在真机上不会生效,只会被当成非法值处理。因此原生配置更适合做简单的明暗适配,不适合做品牌色定制。如果设计稿要求 loading 区域背景为暖色、文字为品牌蓝,就需要跳出页面配置,改用 <scroll-view> 提供的自定义刷新能力。
二、用 scroll-view 的 refresher 插槽自定义 loading
基础库 2.10.1 开始,<scroll-view> 组件增加了 refresher 相关属性,其中最核心的是 refresher-enabled、refresher-triggered、refresher-background 和 refresher-default-style。配合 slot="refresher" 插槽,可以把系统默认刷新区域完全替换成自定义结构,实现在刷新区域放任意动画、图标和文案。
下面是一段 WXML 示例,展示如何用插槽放置一个旋转圆环和动态文字:
<scroll-view
scroll-y
refresher-enabled
refresher-triggered="{{triggered}}"
refresher-threshold="{{80}}"
refresher-background="#f9f9f9"
refresher-default-style="black"
bindrefresherrefresh="onRefresh"
bindrefresherrestore="onRestore"
bindrefresherabort="onAbort"
class="scroll-wrap"
>
<view slot="refresher" class="custom-refresh">
<view class="spinner" style="background-color: {{loadingBg}};"></view>
<text style="color: {{textColor}};">{{loadingText}}</text>
</view>
<view class="content">
<block wx:for="{{list}}" wx:key="id">
<view class="item">{{item.name}}</view>
</block>
</view>
</scroll-view>
对应的 JS 逻辑需要维护 triggered 状态,并在刷新结束后手动复位,否则 <scroll-view> 会一直停留在刷新中。下面这段代码模拟了 1.8 秒的异步刷新过程:
Page({
data: {
triggered: false,
loadingBg: '#ff6600',
textColor: '#333333',
loadingText: '下拉刷新',
list: []
},
onRefresh() {
if (this.data.triggered) return;
this.setData({ triggered: true, loadingText: '正在加载最新数据...' });
setTimeout(() => {
this.setData({
triggered: false,
loadingText: '刷新完成',
list: [
{ id: 1, name: '新内容一' },
{ id: 2, name: '新内容二' }
]
});
wx.showToast({ title: '刷新成功', icon: 'success' });
}, 1800);
},
onRestore() {
this.setData({ loadingText: '下拉刷新' });
},
onAbort() {
this.setData({ triggered: false, loadingText: '下拉刷新' });
}
});
自定义区域是否能顺畅展示,关键在于 refresher-threshold 与 .custom-refresh 高度之间的配合。通常将阈值设为 80 左右,同时把插槽容器高度控制在 60 到 80 之间,松开后动画就不会出现明显跳动。另外,refresher-triggered 必须绑定到 data 中,不要尝试直接在 WXML 中写死布尔值,否则事件回调无法驱动 UI 状态变化。
三、背景色与文字颜色的详细配置
从可配置范围看,原生 JSON 只能通过 backgroundColor 控制刷新区域背景,且该颜色会覆盖在页面背景之上。文字颜色则受 backgroundTextStyle 约束,只支持 dark 或 light。如果页面本身的背景是渐变、图片或深色卡片,原生下拉刷新露出时就会有一条明显色块,视觉上很难统一。
改用 scroll-view 后,refresher-background 可以直接设置任意十六进制颜色或 rgba 值,文字颜色则完全由插槽内 <text> 的 style 决定,可以绑定动态变量实现深色模式切换。比如在夜间模式时把 loadingBg 改为 #ffffff,把 textColor 改为 #dddddd,再把 refresher-background 绑定到变量即可。
样式部分可以配合 CSS 动画做出圆形进度效果:
.scroll-wrap {
height: 100vh;
background: #ffffff;
}
.custom-refresh {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 80px;
padding-top: 20px;
}
.spinner {
width: 24px;
height: 24px;
border-radius: 50%;
border: 2px solid rgba(0, 0, 0, 0.1);
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
需要注意的是,基础库低于 2.10.1 的版本不支持 refresher 插槽,此时想要完全自定义 loading 只能通过监听页面 touch 事件、自己实现一个下拉容器来完成。这种手写方案要处理触摸距离、回弹动画和触发阈值,代码量明显增加,因此在支持新基础库的项目中优先使用 scroll-view 方案会更稳定。
四、常见问题与兼容性避坑
第一个常见问题是原生下拉刷新和 scroll-view 下拉刷新同时开启。页面 JSON 里如果已经配置了 enablePullDownRefresh,又在页面内使用带 refresher 的 scroll-view,很容易出现同时触发两次刷新的情况。一般建议页面级下拉刷新只在非滚动容器场景使用,列表页采用 scroll-view 自定义刷新时,应关闭页面级配置。
第二个问题是刷新结束后 loading 不消失。无论请求成功还是失败,只要 refresher-triggered 为 true,就必须在异步回调中将其设置为 false。如果有多个并发请求,建议用计数器或 Promise.all 来判断全部完成后再复位。
第三点是真机上的文字颜色可能比开发者工具浅或者深,尤其是使用 rgba 透明背景时,不同系统渲染会有差异。调试时最好在 iOS 和 Android 真机上分别查看,避免只在工具里通过。最后还要检查刷新区域与页面顶部安全区的关系,在刘海屏设备上可以给自定义插槽增加 env(safe-area-inset-top) 的 padding,让 loading 不被状态栏遮挡。
微信小程序下拉刷新自定义loading样式修改时间:2026-09-27 17:57:02