$showLoading和$hideLoading非uni-app原生API,须用uni.showLoading/uni.hideLoading;自定义遮罩需v-if控制、高z-index、transform动画;关不掉因异步时机错位,推荐loading计数器管理。

uni-app 里 $showLoading 和 $hideLoading 为什么没效果?
因为这两个方法不是 uni-app 原生 API,是开发者自己挂载到 Vue.prototype 上的封装,官方根本不存在。直接调用会报 TypeError: this.$showLoading is not a function。
- uni-app 官方只提供
uni.showLoading和uni.hideLoading,必须加uni.前缀 - 它们是全局方法,不能在
data或computed里调用,只能在生命周期、事件回调或methods中用 - 注意:H5 端默认用浏览器原生 loading(转圈),App 和小程序才走自定义样式;若想 H5 也统一,得自己覆盖
怎么写一个真能复用的自定义 loading 遮罩组件?
核心是「不依赖平台内置 loading」,用 v-if 控制显隐 + 绝对定位遮罩层,再配合 CSS 动画。别用 uni.showToast 模拟,它不支持遮罩和持续等待。
- 组件内用
props接收visible和text,避免耦合业务逻辑 - 遮罩层必须设
z-index高于所有业务内容(建议 9999),且加pointer-events: none防止拦截点击 - 动画用
transform: scale()+opacity,比display: none更利于性能,也方便做入场/出场过渡 - 示例关键结构:
<view class="loading-mask" v-if="visible"> <view class="loading-content"> <view class="loading-icon"></view> <text class="loading-text">{{ text }}</text> </view> </view>
App 和小程序里遮罩点不透怎么办?
常见于 iOS App 或微信小程序——遮罩层盖住了下层按钮,但点击没反应,其实是 touchmove 被拦截或层级错乱。
- 检查遮罩父容器是否用了
overflow: hidden或position: fixed嵌套过深,这会导致 touch 事件丢失 - 微信小程序中,
cover-view是唯一能盖在 native 组件(如地图、视频)上的方案,但不支持v-if,得用hidden控制显隐 - App 端如果用
web-view,自定义 loading 必须写在 web-view 外层,否则无法覆盖 - 最稳妥做法:把遮罩组件挂到
page根节点下(用uni.createSelectorQuery()或uni.$emit通信),避开组件树限制
为什么 loading 遮罩关不掉?或者关得太快?
本质是「异步时机没对齐」:请求还没结束就调了 uni.hideLoading,或多个请求嵌套导致 hide 被提前触发。
- 别在
then开头就hideLoading,先检查响应状态码、数据结构是否合法,再关 - 用
Promise.finally替代重复写hideLoading,尤其在try/catch场景下 - 避免在同一个页面多个地方独立控制 loading,推荐用全局状态(如
store.loadingCount)做计数器:每次 show +1,hide -1,count === 0 才真正隐藏 - 调试时加个
console.log('hideLoading called'),确认它是否被意外多次调用
loading 遮罩看着简单,但跨端表现、事件穿透、异步节奏这三块最容易出问题。尤其是 App 端真机调试前,务必在 iOS 和 Android 各测一遍点击反馈。


















