这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
如何优雅的基于 element-plus,封装一个梦中情 dialog
优点
摆脱繁琐的 visible 的命名,以及反复的重复 dom。
想法
将 dialog 封装成一个函数就能唤起的组件。如下:
addDialog({
title: "测试", //弹窗名
component: TestVue, //组件
width: "400px", //弹窗大小
props: {
//传给组件的参数
id: 0
},
callBack: (data: any) => {
//当弹窗任务结束后,调用父页面的回掉函数。(比如我新增完成了需要刷新列表页面)
console.log("回调函数", data)
}
})
效果图
基于 el-dialog 进行初步封装
// index.ts
import { reactive } from "vue"
type dialogOptions = {
title: string
component: any
props?: Object
width: string
visible?: any
callBack?: Function
}
export const dialogList: dialogOptions[] = reactive([])
export const addDialog = (options: dialogOptions) => {
dialogList.push(Object.assign(options, { visible: true }))
}
export const closeDialog = (item: dialogOptions, i: number, args?: any, isNativeClose?: boolean) => {
dialogList.splice(i, 1)
if (!isNativeClose) item.callBack && item.callBack(...args)
}
<template>
<Teleport to="body">
<el-dialog
v-for="(item, index) in dialogList"
:key="index"
:title="item.title"
:width="item.width"
v-model="item.visible"
@close="() => closeDialog(item, index, '', true)"
>
<component :is="item.component" v-bind="item.props" @close="(...args:any) => closeDialog(item, index, args)" />
</el-dialog>
</Teleport>
</template>
<script setup lang="ts">
import { dialogList, closeDialog } from "./index"
</script>
- 首先定义了 dialogList,它包含了所有弹窗的信息。
- component 使用 componet is 去动态加载子组件
- addDialog 调用唤起弹窗的函数
- closeDialog 关闭弹窗的函数
在app.vue中挂载
<script setup>
import Mydialog from "@/components/gDialog/index.vue"
</script>
<template>
<router-view />
<Mydialog></Mydialog>
</template>
<style scoped>
</style>
使用
创建一个弹窗组件
<!-- test.vue -->
<template>
父弹窗
<el-button type="primary" @click="openChildDialog">打开子dialog</el-button>
<el-button type="primary" @click="closeDialog">关闭弹窗</el-button>
</template>
<script setup lang="ts">
import { addDialog } from "@/components/gDialog/index"
import childVue from "./child.vue"
const props = defineProps(["id"])
console.log(props.id, "props")
const emit = defineEmits(["close"])
const closeDialog = () => {
emit("close", 1, 2, 34)
}
const openChildDialog = () => {
addDialog({
title: "我是子dialog",
width: "500px",
component: childVue
})
}
</script>
在列表页面唤醒弹窗
<!-- list.vue -->
<template>
列表页
<el-button type="primary" @click="openDialog">打开dialog</el-button>
</template>
<script setup lang="ts">
import { addDialog } from "@/components/gDialog/index"
import TestDialog from "./test.vue"
const openDialog = () => {
addDialog({
title: "我是dialog",
width: "500px",
props:{
id:0
}
component: TestDialog,
callBack: (data: any) => {
//当弹窗任务结束后,调用父页面的回掉函数。(比如我新增完成了需要刷新列表页面)
console.log("回调函数", data)
}
})
}
多层级弹窗嵌套
<!-- child.vue -->
<template>
子弹窗
<el-button type="primary" @click="closeDialog">关闭弹窗</el-button>
</template>
<script setup lang="ts">
import { addDialog } from "@/components/gDialog/index"
const emit = defineEmits(["close"])
const closeDialog = () => {
emit("close", 1, 2, 34)
}
</script>
附上代码
代码