自定义提示确认弹窗-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>
相关推荐
好好好明天会更好1 分钟前
Vue 中 slot 的常用场景有哪些
前端·vue.js
奔赴_向往16 分钟前
【qiankun 踩坑】路由切换回来,子应用 Vuex Store 数据居然还在
前端
sorryhc25 分钟前
【AI解读源码系列】ant design mobile——Image图片
前端·javascript·react.js
老猴_stephanie26 分钟前
Sentry On-Premise 21.7 问题排查与处理总结
前端
sorryhc1 小时前
【AI解读源码系列】ant design mobile——Button按钮
前端·javascript·react.js
VOLUN1 小时前
PageLayout布局组件封装技巧
前端·javascript·vue.js
掘金安东尼1 小时前
React 的 use() API 或将取代 useContext
前端·javascript·react.js
牛马喜喜1 小时前
记录一次el-table+sortablejs的拖拽bug
前端
一枚前端小能手1 小时前
⚡ Vite开发体验还能更爽?这些配置你试过吗
前端·vite
anyup1 小时前
🔥 🔥 为什么我建议你使用 uView Pro 来开发 uni-app 项目?
前端·vue.js·uni-app