自定义提示确认弹窗-vue

最初可运行代码

弹窗组件代码:

(后来发现以下代码可运行,但打包 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 类型检查报错 ###########

  1. 函数接收类没有属性定义
  1. 调用弹窗时未作 组件 非空判断
  1. 接收的回调函数参数,定义的初始值为 null ,无法以函数方式调用
  1. 定义的组件 ref 参数默认值为 null ,无法调用子组件暴露的函数
  1. 子组件定义的参数 与 父组件传递的参数不一致(定义了取消回调,但没有传入)

可以选择传入"取消"操作的回调函数 ,但考虑到此组件在我实际运用时取消没有其它操作,便选择不定义其回调函数

最终可打包的代码

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>
相关推荐
wuhen_n1 小时前
网络请求在Vite层的代理与Mock:告别跨域和后端依赖
前端·javascript·vue.js
小彭努力中1 小时前
193.Vue3 + OpenLayers 实战:圆孔相机模型推算卫星拍摄区域
vue.js·数码相机·vue·openlayers·geojson
用户69371750013846 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
蓝帆傲亦6 小时前
Web 前端搜索文字高亮实现方法汇总
前端
用户69371750013846 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
漫随流水8 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
踩着两条虫9 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程
jzlhll12310 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin
蓝冰凌11 小时前
Vue 3 中 defineExpose 的行为【defineExpose暴露ref变量】详解:自动解包、响应性与实际使用
前端·javascript·vue.js
奔跑的呱呱牛11 小时前
generate-route-vue基于文件系统的 Vue Router 动态路由生成工具
前端·javascript·vue.js