uni.showLoading无法自定义样式因App端调用原生弹窗样式不可控,H5端受z-index和第三方框架影响易被遮挡;需自行实现跨页面v-if浮层组件,通过计数器防并发冲突,并注意CSS兼容性与层级细节。

uni-app 为什么不能直接用 uni.showLoading 自定义样式
因为 uni.showLoading 在 App 端调用的是原生弹窗,iOS/Android 上样式完全不可控;H5 端是 DOM 模拟实现,但受限于 z-index、渲染时机和第三方 UI 框架(如 uView)的覆盖逻辑,经常被遮挡或错位。你改不了它的颜色、大小、动画节奏,甚至在开启下拉刷新("enablePullDownRefresh": true)时,它会直接消失——这不是 bug,是平台限制。
App/H5/小程序三端统一的自定义 Loading 组件怎么挂载
必须绕过 uni.showLoading,自己写一个 v-if 控制的浮层组件,并确保它能跨页面生效:
- 不要在每个页面
<loading></loading>手动引入——维护成本高、易漏、无法响应全局状态 - 不要用
v-show+ 全局变量控制显隐——并发请求下isLoading被覆盖,导致遮罩残留或不显示 - 推荐方案:用
provide/inject或挂载到uni.$loading,并在App.vue的onLaunch和onShow中初始化实例 - H5/PC 端可直接操作
document.body插入 DOM;小程序端需通过Vue.extend构造并$mount到一个固定 id 容器(如#global-loading),再在pages.json的每个页面模板中预留该容器
自定义 Loading 动画的关键 CSS 注意点
小程序对 CSS 支持有限,H5 又容易被其他元素盖住,以下几点漏掉一个就可能白忙活:
-
@keyframes名必须全小写(如spin),大写Spin小程序不识别 - 必须同时写
@-webkit-keyframes spin和@keyframes spin,否则 iOS 真机不转 - 旋转中心用
transform-origin: center,否则动画偏移 - 遮罩层加
pointer-events: none,内部 spinner 加pointer-events: auto,否则点击穿透 -
z-index至少设为9999,uView 导航栏默认是999,不设高会被盖住 - 动画时长建议设为
0.6s,与原生uni.showLoading节奏一致,体验更自然
如何让 Loading 状态真正“全局”且防并发冲突
核心不是“怎么显示”,而是“谁来决定显示/隐藏”以及“什么时候决定”:
- 状态不能存在
this.isLoading或全局变量里——两个接口同时请求,后一个会把前一个的false覆盖掉 - 正确做法:用计数器(
loadingCount),每次请求开始++,complete回调里--,仅当loadingCount === 0时才隐藏遮罩 - 封装请求函数时,仍保留
params.loading开关,但默认true;静默上传、心跳轮询等场景传{ loading: false } - 避免在
success或fail里手动控制遮罩——超时、网络中断、SSL 错误这些路径不会走它们,只靠complete收口才可靠 - 如果用了 Vuex/Pinia,
loadingCount必须是computed,不能直接读store.state.loadingCount,否则响应式失效


















