uni.showLoading必须在uni.request的complete回调中统一调用uni.hideLoading,因success/fail不覆盖超时、网络断开等所有完成路径,仅complete能确保收尾;H5端易被高z-index元素遮挡,App端原生下拉刷新会与fixed层冲突。
全局 loading 不能靠 uni.showloading 堆砌,必须封装请求 + 统一收口在 complete,否则 h5 和小程序端必然卡死或错乱。
为什么 uni.showLoading 直接调用会卡住
因为 uni.request 的 fail 或超时不会自动触发 uni.hideLoading,而 success 又不覆盖所有完成路径。常见错误是只在 success 里写 uni.hideLoading(),结果网络断开、证书错误、跨域拦截时 loading 就永远挂着。
-
uni.request的complete回调才是唯一可靠的“收尾点”,它在 success/fail/time-out 后都执行 - H5 端的
uni.showLoading是 DOM 模拟实现,若页面有z-index更高的元素(比如 uView 导航栏、自定义cover-view),loading 会被遮挡 - App 端原生下拉刷新开启时(
"enablePullDownRefresh": true),会与uni.showLoading的 fixed 层冲突,导致 H5 下动画消失或错位
封装 request 时怎么控制 loading 开关
硬编码所有请求都显示 loading 不现实——轮询心跳、静默上传头像、下拉刷新重试这些场景不该弹窗。必须支持按需开关,且默认开启。
- 封装函数参数加
loading字段:params.loading !== false判断是否启用(默认 true) - 文案可配:
params.loadingText || '加载中',方便不同接口显示“提交中…”“删除中…” - 防重关键:showLoading 必须在
uni.request调用前执行,且不能依赖全局变量存状态(并发请求会互相覆盖) - 别在
success或fail里调uni.hideLoading,只在complete里统一收口
自定义 loading 组件怎么避免动画重置和点击穿透
用 v-if 控制显隐,别用 v-show —— 后者保留 DOM 节点,动画会中断重播;同时要处理 pointer-events,否则 loading 遮罩下层仍可点击。
- 动画用
@keyframes spin定义,transform-origin: center防偏移,时长统一设为0.6s(与原生节奏一致) - CSS 中加
pointer-events: none在遮罩层,或用pointer-events: auto在内部 spinner 上,防止误触 - scoped 样式下,动画名必须小写(小程序不识别大写
Spin),且@-webkit-keyframes和@keyframes都要写全 - 若用 Vuex 控制状态,
loadingShow必须是 computed,不能直接读this.$store.state.xxx(响应式失效)
H5 端 loading 不显示或样式错乱怎么排查
不是代码写错了,大概率是渲染时机或层级问题。H5 的 uni.showLoading 依赖向 document.body 插入 DOM,但某些框架(如 uView)或 router-view 懒加载会让插入时机晚于视图挂载。
- 检查
pages.json是否启用了"enablePullDownRefresh": true,它会抢占 z-index,关掉再试 - 确认是否用了 Vue Router 的异步组件(
import()),需确保 loading 插入早于router-view渲染 - 手动加
style="z-index: 999999 !important"到 loading 的 wrapper 元素上,快速验证是否层级被压 - 真机调试时打开浏览器开发者工具,搜索
uni-toast或uni-loading类名,看对应 DOM 是否存在、是否被display: none或opacity: 0
最易忽略的是:多个请求嵌套时,complete 里调 uni.hideLoading 不做计数判断,会导致后发请求还没 show 就被先完成的 hide 掉。真要支持嵌套,得用 loading 计数器,而不是布尔开关。











