以下是基于 Vue 2 + Element UI 的公共弹窗组件实现方案:
1. 创建公共弹窗组件 (components/GlobalDialog.vue
)
<template>
<el-dialog
:visible.sync="dialogVisible"
:title="title"
:width="width"
:close-on-click-modal="closeOnClickModal"
:show-close="showClose"
:destroy-on-close="destroyOnClose"
@closed="handleClosed"
custom-class="global-dialog"
>
<!-- 内容插槽 -->
<slot name="content"></slot>
<!-- 默认插槽(与content插槽等效) -->
<slot></slot>
<!-- 底部插槽 -->
<template v-if="showFooter" #footer>
<slot name="footer">
<div class="dialog-footer">
<el-button @click="handleCancel" v-if="showCancel">{{ cancelText }}</el-button>
<el-button type="primary" @click="handleConfirm" :loading="confirmLoading">{{ confirmText }}</el-button>
</div>
</slot>
</template>
</el-dialog>
</template>
<script>
export default {
name: 'GlobalDialog',
props: {
// 控制显示
visible: {
type: Boolean,
default: false
},
// 弹窗标题
title: {
type: String,
default: '提示'
},
// 弹窗宽度
width: {
type: String,
default: '50%'
},
// 是否显示底部
showFooter: {
type: Boolean,
default: true
},
// 取消按钮文字
cancelText: {
type: String,
default: '取消'
},
// 确认按钮文字
confirmText: {
type: String,
default: '确定'
},
// 是否显示取消按钮
showCancel: {
type: Boolean,
default: true
},
// 是否显示关闭图标
showClose: {
type: Boolean,
default: true
},
// 点击遮罩关闭
closeOnClickModal: {
type: Boolean,
default: false
},
// 关闭时销毁元素
destroyOnClose: {
type: Boolean,
default: true
}
},
data() {
return {
dialogVisible: this.visible,
confirmLoading: false
}
},
watch: {
visible(newVal) {
this.dialogVisible = newVal
},
dialogVisible(newVal) {
this.$emit('update:visible', newVal)
}
},
methods: {
handleConfirm() {
this.confirmLoading = true
this.$emit('confirm', {
done: () => {
this.confirmLoading = false
this.dialogVisible = false
}
})
},
handleCancel() {
this.$emit('cancel')
this.dialogVisible = false
},
handleClosed() {
this.$emit('closed')
}
}
}
</script>
<style lang="scss">
.global-dialog {
.el-dialog__body {
padding: 20px;
max-height: 70vh;
overflow-y: auto;
}
.dialog-footer {
text-align: right;
}
}
</style>
2. 在父组件中使用
<template>
<div>
<el-button @click="showDialog = true">打开弹窗</el-button>
<global-dialog
:visible.sync="showDialog"
title="用户信息"
width="600px"
@confirm="handleConfirm"
@cancel="handleCancel"
>
<!-- 自定义内容 -->
<el-form label-width="100px">
<el-form-item label="姓名">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="年龄">
<el-input-number v-model="formData.age"></el-input-number>
</el-form-item>
</el-form>
<!-- 自定义底部 -->
<template #footer>
<el-button @click="showDialog = false">关闭</el-button>
<el-button type="primary" @click="submitForm">提交</el-button>
</template>
</global-dialog>
</div>
</template>
<script>
import GlobalDialog from '@/components/GlobalDialog'
export default {
components: { GlobalDialog },
data() {
return {
showDialog: false,
formData: {
name: '',
age: 18
}
}
},
methods: {
handleConfirm({ done }) {
// 模拟异步操作
setTimeout(() => {
this.$message.success('操作成功')
done()
}, 1000)
},
handleCancel() {
this.$message.info('取消操作')
},
submitForm() {
// 自定义提交逻辑
console.log('提交数据:', this.formData)
this.showDialog = false
}
}
}
</script>
核心功能说明
- 双向绑定:使用
.sync
修饰符实现visible
状态同步 - 灵活插槽:
- 默认插槽(内容区域)
content
插槽(等效默认插槽)footer
插槽(底部自定义)
- 事件机制:
confirm
:确认事件(支持异步加载)cancel
:取消事件closed
:完全关闭后触发
- 扩展配置:
- 支持自定义按钮文字
- 控制是否显示底部/关闭按钮
- 是否允许点击遮罩层关闭
- 样式优化:
- 限制最大高度
- 添加滚动条
- 自定义间距
扩展功能建议
添加全局注册(在 main.js
中):
import GlobalDialog from '@/components/GlobalDialog'
Vue.component('GlobalDialog', GlobalDialog)
添加表单验证:
<!-- 在弹窗内容中添加 -->
<el-form ref="form" :model="form" :rules="rules">
<!-- 表单内容 -->
</el-form>
<script>
export default {
methods: {
handleConfirm({ done }) {
this.$refs.form.validate(valid => {
if (valid) {
// 提交逻辑
done()
}
})
}
}
}
</script>
添加全屏功能:
props: {
fullscreen: {
type: Boolean,
default: false
}
}
// 在 el-dialog 上添加
:fullscreen="fullscreen"
添加拖拽功能:
// 在 mounted 中添加
mounted() {
this.$nextTick(() => {
const dialog = document.querySelector('.global-dialog')
// 使用第三方拖拽库或自定义拖拽逻辑
})
}
添加动画效果:
// 在 el-dialog 上添加
:modal-append-to-body="false"
custom-class="animated-dialog"
.animated-dialog {
animation: dialog-fade-in 0.3s;
}
@keyframes dialog-fade-in {
0% { transform: translateY(-20px); opacity: 0; }
100% { transform: translateY(0); opacity: 1; }
}
这种实现方式的优势:
- 完全兼容 Element UI 原有 API
- 保留 Element UI 的全部特性
- 统一的交互体验
- 易于维护和扩展
- 支持复杂的业务场景