用CSS实现可复用Loading组件:定义@keyframes旋转动画,使用border-radius: 50%和border-top-color单独设色确保正圆与高亮,配合v-show控制显隐,避免v-if重置动画;统一动画时长0.6s,transform-origin居中防偏移,scale微缩防锯齿,并注意小程序仅支持小写动画名及scoped样式隔离问题。

uni-app里怎么用CSS写一个可复用的Loading组件
直接用CSS实现Loading,比引入第三方库更轻量、更可控,也避免了uni.showToast或uni.showLoading那种全局遮罩不可定制的问题。关键在于:用@keyframes定义旋转/缩放/呼吸等动画,再通过display或visibility控制显隐,而不是靠v-if频繁销毁重建——否则动画会重置。
常见错误是把animation写在子元素上却忘了加transform-origin,导致旋转中心偏移;或者用opacity: 0隐藏但没配pointer-events: none,结果点击穿透到下层。
- 推荐把Loading封装成独立
.vue文件,通过props接收visible布尔值控制开关 - 动画时长统一设为
0.6s,和uni-app原生showLoading的节奏一致,体验更连贯 - 用
transform: scale(0.8)微缩图标,避免旋转时边缘锯齿(尤其在iOS Webview中)
旋转类Loading的CSS写法(兼容H5/小程序/App)
uni-app跨端时,animation在微信小程序里不支持transform: rotateZ()简写,必须写全rotate(360deg);H5和App则没问题。最稳妥的写法是:
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.loading-spinner {
width: 24px;
height: 24px;
border: 2px solid #e0e0e0;
border-top-color: #007AFF;
border-radius: 50%;
animation: spin 0.6s linear infinite;
}
注意两点:一是border-radius: 50%必须显式声明,某些安卓WebView里默认不是正圆;二是border-top-color单独设色,比用border-color再覆盖更可靠。
立即学习“前端免费学习笔记(深入)”;
如何让Loading跟随数据请求状态自动开关
别在每个uni.request前后手动调this.loading = true/false,容易漏掉catch分支。应该封装请求函数,统一处理:
async apiGetUser() {
uni.showLoading({ title: '加载中' }); // 可选:保留原生提示作兜底
try {
const res = await uni.request({ url: '/user' });
this.userData = res.data;
} catch (err) {
console.error(err);
} finally {
uni.hideLoading();
}
}
但如果要用自定义CSS Loading,就改用响应式变量:
- 在data里声明
loading: false - 在methods里封装
requestWithLoading,内部自动设置this.loading = true→ 请求 →this.loading = false - 模板中用
v-show="loading"而非v-if,保证DOM始终存在,动画不中断
小程序真机调试时Loading不转?检查这三点
微信小程序开发工具里正常,真机上不动,大概率是以下原因:
- 动画名用了大写字母(如
@keyframes Spin),小程序只认小写spin -
animation写在class里但被scoped样式隔离了,需加deep或提至全局样式 - 父容器设置了
overflow: hidden且Loading元素超出边界,动画被裁剪(尤其用position: absolute时)
最省事的排查方式:在真机上打开vConsole,选中Loading元素,看computed style里animation是否生效,以及transform值是否在变化。


















