Vue 2 进度提示完整代码
一、排查常见失效原因(核心问题)
大概率是这几个原因:
- 延迟设置(默认 300ms):如果请求耗时短于 300ms,加载提示会被跳过(避免闪烁),测试时需模拟长请求;
- DOM 挂载失败:loading 实例未正确添加到 body,或路径引入错误;
- 样式层级问题:z-index 不够,被页面元素遮挡;
- 调用时机错误:
hideLoading调用过早,或未在finally中执行; - 文件路径错误:Loading 组件 / 工具函数的引入路径写错。
二、方案(简化版,无延迟,优先确保显示)
1. Loading 组件(src/components/Loading.vue)
去掉延迟逻辑,提高样式层级,确保肉眼可见:
vue
<template>
<div class="loading-container" v-if="isShow">
<!-- 遮罩层:浅背景更容易看到 -->
<div class="loading-mask"></div>
<!-- 加载内容:居中显示 -->
<div class="loading-content">
<div class="loading-spinner"></div>
<p class="loading-text">{{ text }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'Loading',
props: {
// 是否显示(直接控制,无延迟)
isShow: {
type: Boolean,
default: false
},
// 提示文字
text: {
type: String,
default: '加载中...'
}
}
}
</script>
<style scoped>
/* 核心:提高z-index到99999,避免被遮挡 */
.loading-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 99999; /* 远高于普通元素 */
display: flex;
justify-content: center;
align-items: center;
}
/* 浅白色遮罩,确保加载框显眼 */
.loading-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.8);
}
/* 加载框样式:白色背景+阴影 */
.loading-content {
background-color: #fff;
padding: 20px 30px;
border-radius: 8px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
text-align: center;
}
/* 旋转加载图标(确保动画生效) */
.loading-spinner {
width: 40px;
height: 40px;
border: 4px solid #f0f0f0;
border-top: 4px solid #42b983; /* Vue 绿色,显眼 */
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 10px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-text {
color: #333;
font-size: 14px;
margin: 0;
}
</style>
2. 加载工具函数(src/utils/loading.js)
简化逻辑,确保实例正确挂载到 body:
javascript
import Vue from 'vue'
import Loading from '../components/Loading.vue' // 确认路径正确!
// 创建组件构造器
const LoadingConstructor = Vue.extend(Loading)
let loadingInstance = null // 存储唯一实例
// 显示加载提示
export const showLoading = (options = {}) => {
// 先销毁已有实例,避免重复显示
if (loadingInstance) {
hideLoading()
}
// 创建实例并挂载(生成$el)
loadingInstance = new LoadingConstructor({
propsData: {
isShow: true,
text: options.text || '加载中...'
}
}).$mount() // 挂载但不指定节点,手动添加到DOM
// 强制添加到body(关键:确保DOM存在)
document.body.appendChild(loadingInstance.$el)
// 手动触发更新,避免渲染延迟
loadingInstance.$forceUpdate()
}
// 隐藏加载提示
export const hideLoading = () => {
if (loadingInstance) {
// 直接隐藏
loadingInstance.isShow = false
// 移除DOM并销毁实例
setTimeout(() => {
if (loadingInstance && loadingInstance.$el) {
document.body.removeChild(loadingInstance.$el)
}
loadingInstance = null // 重置实例
}, 100)
}
}
// 注册到Vue原型,全局可用
Vue.prototype.$showLoading = showLoading
Vue.prototype.$hideLoading = hideLoading
3. 确认 main.js 引入(路径必须正确)
javascript
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// 引入加载工具(确认路径:src/utils/loading.js)
import './utils/loading'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')
三、快速验证(必做!确保能看到加载提示)
创建测试页面(src/views/TestLoading.vue),模拟 5 秒长请求,确保加载提示显示:
vue
<template>
<div >
<h2>测试加载提示</h2>
<!-- 点击按钮触发长请求 -->
<button @click="triggerLongRequest" >
点击触发5秒长请求
</button>
</div>
</template>
<script>
export default {
name: 'TestLoading',
methods: {
async triggerLongRequest() {
// 1. 立即显示加载提示(无延迟)
this.$showLoading({ text: '正在加载大数据...' })
try {
// 2. 模拟5秒长请求(足够看到加载提示)
await new Promise(resolve => setTimeout(resolve, 5000))
alert('加载完成!')
} catch (error) {
alert('加载失败!')
} finally {
// 3. 无论成功/失败,都隐藏提示
this.$hideLoading()
}
}
}
}

浙公网安备 33010602011771号