自定义提示确认弹窗-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>
相关推荐
TrisighT23 分钟前
Electron 鸿蒙 PC 上点外链唤醒应用,我试了 6 种写法只有 1 种能跑
前端·electron·harmonyos
天才熊猫君1 小时前
配置与数据分离:一种可视化搭建的属性编辑方案
前端·javascript
林希_Rachel_傻希希2 小时前
web性能之相关路径——AI总结
前端·javascript·面试
竹林8182 小时前
用 wagmi v2 踩坑两天,我终于搞懂了多链钱包切换在 DeFi 前端中的正确姿势
前端·javascript
用户2136610035722 小时前
Vue项目搜索功能与面包屑导航
前端·javascript
ch_09182 小时前
从0构建SDK第4节:实现 ReflectionAgent 的自我反思循环
typescript·agent·ai编程
星栈2 小时前
LiveView 的实时通信,爽是爽,但 PubSub 和广播也最容易把自己绕晕
前端·前端框架·elixir
用户2930750976692 小时前
告别关键词匹配,拥抱向量语义 —— RAG 搜索从零到一
前端
独孤留白2 小时前
从C到Rust:告别 C 的"指针 + 长度"手动模式
前端·rust
飞天狗2 小时前
TypeScript类型系统其实是个图灵完备的语言
面试·typescript