vue复杂按钮loading实现
实现复杂按钮 Loading 效果
在 Vue 中实现复杂按钮的 Loading 效果,可以通过结合状态管理、CSS 动画和图标库来实现。以下是几种常见方法:
使用 Element UI 或 Ant Design Vue 的 Loading 按钮
如果项目中使用了 Element UI 或 Ant Design Vue,可以直接使用它们提供的 Loading 按钮组件:

<template>
<el-button type="primary" :loading="isLoading" @click="handleClick">
提交
</el-button>
</template>
<script>
export default {
data() {
return {
isLoading: false
}
},
methods: {
handleClick() {
this.isLoading = true
setTimeout(() => {
this.isLoading = false
}, 2000)
}
}
}
</script>
自定义 Loading 按钮
对于更复杂的自定义需求,可以创建一个可复用的 Loading 按钮组件:
<template>
<button
class="custom-button"
:disabled="loading"
@click="$emit('click')"
>
<span v-if="!loading">{{ text }}</span>
<div v-else class="loading-content">
<svg class="spinner" viewBox="0 0 50 50">
<circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
</svg>
<span>{{ loadingText }}</span>
</div>
</button>
</template>
<script>
export default {
props: {
text: {
type: String,
default: 'Submit'
},
loadingText: {
type: String,
default: 'Processing...'
},
loading: {
type: Boolean,
default: false
}
}
}
</script>
<style scoped>
.custom-button {
position: relative;
padding: 10px 20px;
border: none;
border-radius: 4px;
background-color: #409eff;
color: white;
cursor: pointer;
transition: all 0.3s;
}
.custom-button:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.loading-content {
display: flex;
align-items: center;
justify-content: center;
}
.spinner {
animation: rotate 2s linear infinite;
width: 20px;
height: 20px;
margin-right: 8px;
}
.spinner .path {
stroke: white;
stroke-linecap: round;
animation: dash 1.5s ease-in-out infinite;
}
@keyframes rotate {
100% {
transform: rotate(360deg);
}
}
@keyframes dash {
0% {
stroke-dasharray: 1, 150;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -35;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -124;
}
}
</style>
结合 Vuex 管理全局 Loading 状态
对于需要跨组件共享的 Loading 状态,可以使用 Vuex:

// store.js
export default new Vuex.Store({
state: {
isLoading: false
},
mutations: {
setLoading(state, payload) {
state.isLoading = payload
}
},
actions: {
async submitForm({ commit }) {
commit('setLoading', true)
try {
await api.submit()
} finally {
commit('setLoading', false)
}
}
}
})
在组件中使用:
<template>
<button :disabled="$store.state.isLoading">
<span v-if="!$store.state.isLoading">Submit</span>
<span v-else>Loading...</span>
</button>
</template>
使用 CSS 实现进度条式 Loading
对于需要显示进度的按钮,可以添加进度条效果:
<template>
<div class="progress-button" @click="startProgress">
<div class="progress-bar" :style="{ width: progress + '%' }"></div>
<span class="button-text">
{{ progress === 100 ? 'Complete' : progress > 0 ? 'Uploading...' : 'Upload' }}
</span>
</div>
</template>
<script>
export default {
data() {
return {
progress: 0
}
},
methods: {
startProgress() {
if (this.progress > 0) return
const interval = setInterval(() => {
this.progress += 5
if (this.progress >= 100) {
clearInterval(interval)
setTimeout(() => {
this.progress = 0
}, 1000)
}
}, 200)
}
}
}
</script>
<style scoped>
.progress-button {
position: relative;
display: inline-block;
padding: 10px 20px;
background-color: #f0f0f0;
color: #333;
border: none;
border-radius: 4px;
overflow: hidden;
cursor: pointer;
}
.progress-bar {
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: #4CAF50;
transition: width 0.3s ease;
}
.button-text {
position: relative;
z-index: 1;
}
</style>
这些方法可以根据项目需求进行组合和扩展,实现各种复杂的按钮 Loading 效果。






