父子组件动态生成方法
大约 2 分钟
父子组件动态生成方法
在 Vue 3 中,由于组合式 API 的引入,我们需要在组合式 API 中获取 $emit 方法并使用它来触发事件。在 Setup 函数中,我们可以通过 getCurrentInstance 方法获取当前组件实例,然后从实例对象中获取 $emit 方法并使用它来触发事件,例如:
<template>
<button @click="clickEvent">点击触发事件</button>
</template>
<script setup>
import { getCurrentInstance } from 'vue'
function clickEvent() {
const instance = getCurrentInstance()
instance?.emit?.('event', '参数')
}
</script>
案例
父组件
<!-- 在这个例子中,我们使用 getCurrentInstance 方法获取当前组件实例,并通过 instance?.emit?.('event', '参数') 语句调用实例的 $emit 方法触发事件。由于 instance 和 instance.$emit 可能会为空值,我们使用了可选链语法来避免程序抛出错误。 -->
<template>
<div class="container">
<button @click="dialogData.status = true">点击</button>
</div>
<ConfirmDialog :dialogData="dialogData" @dialogConfirmFunc0="onDialogConfirmFunc0" @dialogConfirmFunc1="onDialogConfirmFunc1" @dialogConfirmFunc2="onDialogConfirmFunc2" @dialogCancelFunc0="dialogData.status=false"></ConfirmDialog>
</template>
<script setup lang="ts">
import ConfirmDialog from '@/components/confirmDialog.vue'
import { ref, reactive, onMounted } from 'vue'
import { Plus } from '@element-plus/icons-vue'
let dialogData = ref({
status: false,
type:"YELLOW",
title: "请确认是否批量结算",
text: "请确认是否结算?点击确认后列表中的全部账单将确认结算,确定后将不允许撤销",
cancelText: ["取消"],
confirmText: ["确定","确认1",'确认3']
})
onMounted(()=>{
})
const onDialogConfirmFunc0 = ()=>{
console.log('1111111111')
}
const onDialogConfirmFunc1 = ()=>{
console.log('222222222222')
}
const onDialogConfirmFunc2 = ()=>{
console.log('33333333')
}
</script>
<style scoped lang="scss">
.container {
height: 100%;
}
</style>
子组件
<!-- 通用确认弹框 -->
<template>
<el-dialog v-model="dialogData.status" :show-close="false" :align-center="true" width="400px">
<template #header="{ close, titleId, titleClass }">
<div class="dialog_header">
<div :id="titleId" class="dialogs" :class="[dialogData.type]">
<!-- <div src="@/assets/icon/dialog_1.png" alt=""> -->
<div class="dialogs_img"></div>
<div class="dialogs_title">{{ dialogData.title }}</div>
</div>
<el-icon color="#909399" @click="dialogData.status = false">
<Close />
</el-icon>
</div>
</template>
<div class="dialog_text">
{{ dialogData.text }}
</div>
<template #footer>
<span class="dialog-footer">
<template v-for="(item, index) in dialogData.cancelText" :key="index">
<el-button class="set_other_btn" @click="onCancel(index)">{{ item }}</el-button>
</template>
<template v-for="(item, index) in dialogData.confirmText" :key="index">
<el-button type="primary" @click="onConfirm(index)" :color="globalBtnColor">
{{ item }}
</el-button>
</template>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { globalBtnColor } from '@/constants'
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
const props = defineProps({
dialogData: {
type: Object,
default: {
status: false,//状态
type:"",//颜色类型,枚举:RED,YELLOW,GREEN
title: "",//标题
text: "",//内容
cancelText: [""],//确认组
confirmText: [""]//取消组
}
},
})
let btnList: any = []
const instance = getCurrentInstance()
props.dialogData.cancelText.forEach((item: any, index: number) => {
btnList.push("dialogCancelFunc" + index)
})
props.dialogData.confirmText.forEach((item: any, index: number) => {
btnList.push("dialogConfirmFunc" + index)
})
const onConfirm = (index: number) => {
instance?.emit?.("dialogConfirmFunc" + index, '')
}
const onCancel = (index: number) => {
instance?.emit?.("dialogCancelFunc" + index, '')
}
</script>
<style scoped lang="scss">
.dialog_header {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.dialogs{
display: flex;
align-items: center;
.dialogs_img {
width: 24px;
height: 24px;
background-size: 100% 100%;
background-repeat: no-repeat;
}
.dialogs_title {
margin-left: 8px;
color: #F59300;
font-size: $fontSizeSixteen;
font-weight: bold;
}
}
.YELLOW {
.dialogs_img {
background-image: url('@/assets/icon/dialog_1.png');
}
.dialogs_title {
color: #F59300;
}
}
.RED {
.dialogs_img {
background-image: url('@/assets/icon/dialog_2.png');
}
.dialogs_title {
color: #F56C6C;
}
}
.GREEN {
.dialogs_img {
background-image: url('@/assets/icon/dialog_3.png');
}
.dialogs_title {
color: #67C23A;
}
}
.dialog_text {
margin-left: 32px;
}
</style>