Vue 3 + Element Plus 自定义弹出框组件实践
在Vue 3项目中,使用Element Plus构建弹出框是一项常见的任务。为了简化这个过程,我们可以封装一个公共组件,使弹出框的调用变得简单而高效。本文将介绍如何通过Vue 3和Element Plus,使用一个自定义的弹出框组件实现这一目标。
1. 弹出框组件封装
首先,我们封装了一个通用的弹出框组件,具体实现位于 util.js
文件中。通过 initInstance
方法,我们可以动态创建一个弹出框实例,并将其挂载到指定的容器上。以下是简要代码:
// util.js
import { h, render } from 'vue';
export function initInstance(component, container, option) {
const vNode = h(component, option);
render(vNode, container);
document.body.appendChild(container.firstElementChild);
return vNode.component;
}
export function getContainer() {
return document.createElement('div');
}
2. 自定义弹出框配置
接下来,我们定义了一个名为 portPop
的自定义弹出框配置。这个配置使用了前面封装的通用方法,同时为弹出框提供了一些特定的配置。以下是简要代码:
// common.js
import { initInstance, getContainer } from "./util";
import PortPop from "../components/PortPop";
const instanceMap = new Map();
export const portPop = (option, call) => {
const container = getContainer();
let opt = {
...option,
onComfrim: (data) => {
call(data);
},
onVanish: () => {
render(null, container);
instanceMap.delete(vm);
},
};
const component = initInstance(PortPop, container, opt);
const vm = component.proxy;
component.exposed.openDialog();
instanceMap.set(vm, { option: opt });
};
3. 弹出框组件实现
首先,我们要先封装一下el-dialog组件
<template>
<el-dialog
:model-value="modelValue"
:title="title"
:width="width"
:modal="modal"
draggable
destroy-on-close
:close-on-click-modal="false"
append-to-body
:before-close="beforeClose"
@close="dialogColse"
@closed="dialogColsed"
>
<slot />
<template #footer>
<span class="dialog-footer">
<slot name="footer" />
</span>
</template>
</el-dialog>
</template>
<script setup name="Dialog">
import { ElDialog } from "element-plus";
const props = defineProps({
modelValue: {
type: [Boolean],
default: false,
},
title: {
type: [String],
default: "",
},
width: {
type: [String],
default: "",
},
modal: {
type: [Boolean],
default: false,
},
beforeClose: [Function],
});
const emits = defineEmits(["update:modelValue", "onClosed", "closed"]);
function dialogColse() {
emits("update:modelValue", false);
}
function dialogColsed() {
emits("onClosed", false);
emits("closed", false);
}
</script>
<style lang="scss">
</style>
最后,我们实现了具体的弹出框组件 PortPop
,这个组件使用了 Element Plus 的 Dialog
组件,并在其中嵌套了一些其他组件,以实现特定的功能。以下是简要代码:
<template>
<div>
<Dialog :title="props.title" v-model="dialog" width="920px">
<!-- ... 弹出框内容 ... -->
<template #footer>
<div class="dialog-footer">
<el-button type="primary" size="small" @click="confrim">
确定
</el-button>
<el-button @click="dialog = false" size="small">取消</el-button>
</div>
</template>
</Dialog>
</div>
</template>
<script setup lang="tsx">
import {
nextTick,
ref, useAttrs,
} from 'vue'
import Dialog from '@/components/dialog'
import {
ElInput,
ElButton,
} from 'element-plus'
const props = defineProps({
title: {
type: [String],
default: '',
},
type: {
type: [String],
default: '',
},
})
const emits = defineEmits(['comfrim'])
const attrs = useAttrs()
const dialog = ref(false)
function openDialog() {
dialog.value = true
}
const confrim = async () => {
emits('comfrim', "传递给父组件的数据")
nextTick(() => {
dialog.value = false
})
}
defineExpose({ openDialog })
</script>
<style lang="scss">
</style>
4. 使用自定义弹出框组件
最终,我们可以在需要调用弹出框的地方,简单地执行portPop
方法,并传递相应的配置和回调函数。这样,弹出框就会显示出来,用户可以与之交互。
// 在需要的地方调用自定义弹出框
import { portPop } from "./customDialog";
// 示例调用
portPop({ title: '自定义弹出框', defaultKeyword: '关键字' }, (data) => {
// 处理弹出框确认后的数据
console.log('用户选择的数据:', data);
});