app端uni.showloading不能用,因其调用原生弹窗,样式不可定制、无法覆盖状态栏/导航栏、不支持z-index和点击穿透;必须改用v-show控制的全局dom遮罩组件。

App端uni.showLoading为什么不能用
因为uni.showLoading在iOS/Android真机上走的是原生弹窗通道,不是渲染层DOM,所以你写的CSS完全无效,改z-index、background、animation都没用。它默认白底黑字+转圈,卡在状态栏下面、导航栏上面,遮不住页面内容,也不支持点击穿透——这不是bug,是设计如此。
常见错误现象包括:uni.showLoading调用了但没显示(其实是被原生导航栏盖住了)、uni.hideLoading不响应(多层原生弹窗冲突)、H5里看着正常但App端全失效。
- 别在App端对
uni.showLoading做样式覆盖尝试,100%徒劳 - 如果同时用了
uni.showToast或uni.showModal,极大概率触发原生弹窗栈混乱,导致loading卡死 - H5和小程序端可以部分定制,但App端必须换路子
怎么写一个真正可用的全局Loading组件
核心是把它做成一个常驻的<view></view>节点,用v-show控制显隐(不用v-if,避免重复挂载开销),靠position: fixed + z-index: 9999强行覆盖全屏。
关键实操点:
- 组件内不要用
uni.showLoading,只依赖props或store驱动v-show - 遮罩层必须设
top: 0; left: 0; width: 100vw; height: 100vh;,否则在某些Android机型上会漏出底部内容 - 动画用
@keyframes+transform: rotate()最稳,避免用animation: spin这种模糊命名,防止被其他CSS重置 - 如果用Vue 3 + Composition API,推荐用Pinia store统一管理
isLoading状态,而不是app.vue的globalData(后者跨页面同步有延迟)
示例结构(components/GlobalLoading.vue):
<template><view v-show="isLoading" class="loading-overlay"><view class="spinner"></view><view class="text">加载中...</view></view></template><script setup>
import { useLoadingStore } from '@/store/loadingStore'
const store = useLoadingStore()
const isLoading = $computed(() => store.isLoading)
</script>
如何在请求和页面跳转时自动控制Loading
不能靠手动每个uni.navigateTo前后加show/hide,容易漏、难维护。得用拦截机制。
实操建议:
- 在
uni.addInterceptor('request')里统一store.show(),在response和fail拦截器里调store.hide()——注意并发请求要防抖,避免多次show导致闪烁 - 页面跳转用
uni.$on('route:start')和uni.$on('route:end')(需在app.vue中注册),比监听onLoad更及时 - 如果用了
uni-app的easycom,确保components/GlobalLoading.vue文件名和目录名严格一致(如components/GlobalLoading/GlobalLoading.vue),否则HBuilderX可能不自动引入 - 别在
onPullDownRefresh里单独控制loading,它和全局loading逻辑冲突,优先用store统一调度
容易被忽略的兼容性细节
真机测试时最容易翻车的不是逻辑,而是这些小地方:
- iOS上
fixed定位在webview里有时会“粘”在滚动位置不动,得加transform: translateZ(0)强制硬件加速 - 某些Android 12+系统对
z-index > 9999有拦截,别设成99999,就用9999最稳妥 - 如果项目启用了
subNVue或原生插件,自定义loading必须加pointer-events: none,否则会挡住底层原生控件的点击 - 字体大小用
rpx而非px,否则在iPhone SE等小屏上文字溢出遮罩层
最复杂的点其实是状态同步时机——比如请求还没发完,用户就点了返回,这时候loading该不该立刻消失?得在beforeUnload钩子里加cancel逻辑,不然会出现“跳到上一页还挂着loading”的诡异现象。











