最初可运行代码
弹窗组件代码:
(后来发现以下代码可运行,但打包 typescript 类型检查出错,可打包的代码在文末)
html
<template>
<div v-if="isVisible" class="dialog">
<div class="dialog-content">
<div style="padding: 40px 40px; text-align: center">{{message}}</div>
<div style="display: flex; border-top: 1px solid #d2d0d0">
<div @click="cancel" class="dialog-button">取消</div>
<div style="border-right: 1px solid #d2d0d0"></div>
<div @click="handleConfirm" class="dialog-button" style="color: #4e8fd3">确定</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const isVisible = ref(false);
const message = ref('');
const confirmCallback = ref(null)
const cancelCallback = ref(null);
const showDialog = (params = {} ) => {
isVisible.value = true;
message.value = params.message || '提示内容';
confirmCallback.value = params.confirmCallback || null;
cancelCallback.value = params.cancelCallback || null;
};
const handleConfirm = () => {
if (confirmCallback.value) {
confirmCallback.value();
}
isVisible.value = false;
};
const cancel = () => {
if (cancelCallback.value) {
cancelCallback.value();
}
isVisible.value = false;
};
defineExpose({
showDialog
});
</script>
<style scoped>
.dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
}
.dialog-content {
background-color: #fff;
border-radius: 10px;
width: 80%;
}
.dialog-button {
flex-grow: 1;
text-align: center;
padding: 20px 0;
}
</style>
效果:更适用于移动端
弹窗显示:
html
<template>
<div>
<button @click="openDialog">打开弹窗</button>
<ChildDialg ref="dialogRef" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
// 1. 引入子组件
import ChildDialg from "@/views/components/ChildDialg.vue";
// 2. 定义子组件 ref 参数
const dialogRef = ref(null);
const openDialog = () => {
// 3. 弹窗显示
dialogRef.value.showDialog({
message: '内容',
confirCallback: () => {
}
});
};
</script>
打包 typescript 检查错误修复
######## 项目打包,typescript 类型检查报错 ###########
- 函数接收类没有属性定义
- 调用弹窗时未作 组件 非空判断
- 接收的回调函数参数,定义的初始值为 null ,无法以函数方式调用
- 定义的组件 ref 参数默认值为 null ,无法调用子组件暴露的函数
- 子组件定义的参数 与 父组件传递的参数不一致(定义了取消回调,但没有传入)
可以选择传入"取消"操作的回调函数 ,但考虑到此组件在我实际运用时取消没有其它操作,便选择不定义其回调函数
最终可打包的代码
html
<template>
<div v-if="isVisible" class="dialog">
<div class="dialog-content">
<div style="padding: 40px 40px; text-align: center">{{message}}</div>
<div style="display: flex; border-top: 1px solid #d2d0d0">
<div @click="cancel" class="dialog-button">取消</div>
<div style="border-right: 1px solid #d2d0d0"></div>
<div @click="handleConfirm" class="dialog-button" style="color: #4e8fd3">确定</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const isVisible = ref(false);
const message = ref('');
const confirmCallback = ref(() => {})
const cancelCallback = ref(() => {});
const showDialog = (params = {
message: '提示内容',
confirmCallback: () => {}
} ) => {
isVisible.value = true;
message.value = params.message;
confirmCallback.value = params.confirmCallback;
};
const handleConfirm = () => {
if (confirmCallback.value) {
confirmCallback.value();
}
isVisible.value = false;
};
const cancel = () => {
if (cancelCallback.value) {
cancelCallback.value();
}
isVisible.value = false;
};
defineExpose({
showDialog
});
</script>
<style scoped>
.dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
}
.dialog-content {
background-color: #fff;
border-radius: 10px;
width: 80%;
}
.dialog-button {
flex-grow: 1;
text-align: center;
padding: 20px 0;
}
</style>
html
<template>
<div>
<button @click="openDialog">打开弹窗</button>
<ChildDialg ref="dialogRef" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
// 1. 引入子组件
import ChildDialg from "@/views/components/ChildDialg.vue";
// 2. 定义子组件 ref 参数
const dialogRef = ref<InstanceType<typeof DialogView> | null>(null)
const openDialog = () => {
// 3. 弹窗显示
if(dialogRef.value) {
dialogRef.value.showDialog({
message: '内容',
confirCallback: () => {
}
});
}
};
</script>