App端需禁用原生下拉刷新(pages.json设"enablePullDownRefresh": false),改用scroll-view的refresher插槽挂载SVG动画,并手动管理uni.stopPullDownRefresh()状态。

App端必须关掉原生下拉,才能用SVG动画
uni-app 的 App 端(iOS/Android)下拉刷新默认是原生容器控制的,enablePullDownRefresh 一开,系统就接管整个手势和 loading 动画,你写的 SVG 根本没机会显示。想让自定义 SVG 动画生效,第一步就是彻底禁用它:"enablePullDownRefresh": false 必须写在 pages.json 对应页面的 style 里——不是写在 JS 里,也不是靠 uni.startPullDownRefresh() 触发时才关。
关掉之后,你得自己监听触顶和下拉距离。别用 scroll-view 模拟(它在 App 端对 touchmove 响应不稳定),而是用页面根容器 + scrolltoupper 事件配合 scrollTop 判断是否触顶,再结合 touchstart/touchmove 计算 deltaY 实现拖拽感。
SVG路径动画在小程序平台根本跑不动
微信小程序渲染层不支持 stroke-dasharray 和 stroke-dashoffset 的 CSS 动画,哪怕你写了 @keyframes 或 inline style 变更,也不会重绘路径。这不是写法问题,是底层限制。H5 和 App 端可以用 document.querySelector('path').getTotalLength() + uni.createAnimation() 驱动 offset 变化,但小程序必须绕开路径描边方案。
- 小程序推荐改用
<uni-icons>或<image>(如 APNG 动画图)做刷新图标,通过v-if切换状态 - 如果坚持用 SVG,得把动画逻辑改成 transform 缩放/旋转,例如
animation.rotate(360).step(),避开 stroke 相关属性 - 别把 SVG 写在
v-for里或用v-html插入,ref 很可能拿不到真实 DOM 节点;外层套个<view class="svg-wrapper">,再用uni.createSelectorQuery().select('.svg-wrapper').select('path')查找
scroll-view 的 refresher 插槽才是跨端最稳的入口
如果你只针对 H5 + App(不强求小程序),scroll-view 的 refresher-enabled 是目前唯一能稳定挂载自定义 SVG 的位置。它不依赖页面级配置,也不需要手动监听 touch,直接用插槽即可:
<scroll-view
scroll-y
refresher-enabled
refresher-threshold="80"
refresher-background="transparent"
refresher-default-style="none"
@refresherrefresh="onRefresh"
@refresherpulling="onPulling"
@refresherrestore="onRestore"
>
<template #refresher>
<view class="refresh-icon">
<svg viewBox="0 0 100 100" width="60" height="60">
<path
id="loading-path"
d="M50,20 A30,30 0 0,1 80,50"
fill="none"
stroke="#409eff"
stroke-width="6"
/>
</svg>
</view>
</template>
<!-- 列表内容 -->
</scroll-view>关键点:refresher-default-style="none" 必须设,否则系统默认黑圈会盖住你的 SVG;refresher-threshold 建议设到 70–100px,太小 iOS 容易误触发;@refresherpulling 里可以动态更新 SVG 的 transform 或 stroke-dashoffset 值,实现“越拉越满”的视觉反馈。
松手后 loading 状态必须手动管理
无论你用哪种方式触发刷新,只要进了 onRefresh 或 @refresherrefresh 回调,就必须显式调用 uni.stopPullDownRefresh()(App/H5)或设置 refresher-triggered=false(scroll-view 方案)。漏掉这步,动画会卡死,且后续下拉无法再触发回调——因为底层状态没重置。
更隐蔽的问题是:请求失败时更容易忘记调用。比如接口超时、token 过期、网络中断,这些情况都得包在 try/catch 里,确保 uni.stopPullDownRefresh() 或 this.triggered = false 执行。否则用户会以为“页面坏了”,反复下拉也没反应。
SVG 动画本身没有生命周期钩子,它的启停完全依赖你对 triggered、status 这类响应式变量的控制。别指望动画播完自动清理,所有状态切换都要你亲手写清楚。


















