封装的原因
1.之前我在做项目时,由于总是碰到需要弹出表单的场景,每次需要写一遍弹窗的逻辑使得代码很冗余,自己都看不下去的情况。
2.由于是刚开始学习vue,对vue的组件之间的传参不是很了解,所以一开始我使用的是store+watch即状态管理库和监听器实现父子组件之间的传参,但是我每次新增一个业务模块,我都需要去改动store还有父子组件,其实也很麻烦,最近看见了一个代码看起很简洁且实现简单的封装弹窗的方法,于是在这里记录一下。
实现效果
实现父组件点击新增弹框的按键,出现弹框,点击确认或者取消,弹框消失,其他内容可以自行定义。
代码实现
//弹框组件Dialog.vue
<template>
<el-dialog :title="title" :model-value="visible" :before-close="onClose" append-to-body :close-on-click-modal="false" :width="width + 'px'">
//在这儿放置一个name为content的具名插槽,他会展示父组件里面传过来的插槽内容
<slot name="content"></slot>
<template #footer>
//子组件通过自定义事件传递
<el-button type="danger" @click="onClose">取消</el-button>
<el-button type="primary" @click="onConfirm">确定</el-button>
</template>
</el-dialog>
</template>
<script lang='ts' setup>
import { withDefaults } from 'vue'
//定义dialog的属性
interface DialogProps {
title: string,//弹窗的标题
visible: boolean,//是否隐藏弹窗
width: number,
height: number
}
//接受父组件传过来的信息
//withDefaults用于将默认配置对象与传递的配置对象合并,并赋予一个默认值
const props = withDefaults(defineProps<DialogProps>(), {
title: '标题',
//父组件只传过来visible,所以将父组件的传过来的值与默认配置里面的visible合并
visible: false,
width: 630,
height: 280
});
//子组件通过自定义事件将数据传递给父组件
let emit = defineEmits(['onClose','onConfirm'])
//定义弹框的关闭
const onClose = () => {
//data1是onClose里面的参数,随着自定义事件一起传递给父组件,可写也可不写
emit("onClose",data1);
};
//定义弹框的确定
const onConfirm = () => {
emit("onConfirm",data2);
};
</script>
<style lang='scss' scope>
</style>
//父组件Dashboard.vue
<template>
<el-container>
<el-header>title</el-header>
<el-main>
<el-button @click="addButton">新增</el-button>
//
<Dialog :visible="dialog.visible" @onClose="onClose" @onConfirm="onConfirm">
<template v-slot=content >
//自定义弹框里面的内容,并将内容传送给子组件
</template>
</Dialog>
</el-main>
</el-container>
</template>
<script lang='ts' setup>
import {reactive} from 'vue'
import Dialog from '../components/Dialog'
//定义弹框属性
const dialog = reactive({
title:'新增',
visible:false,
})
//实现子组件传过来的自定义事件
//弹框关闭
const onClose = (data1) => {
//在弹框关闭之前,可以定义一些父组件应该执行的操作
dialog.visible = false;
};
//弹框确定
const onConfirm = (data2) => {
//在弹框关闭之前,可以定义一些父组件应该执行的操作
dialog.visible = false;
};
const addButton = ()=>{
dialog.visible = true;
}
</script>
<style lang='scss' scope>
</style>