Vue3对话框(Dialog)
Vue2对话框(Dialog)
可自定义设置以下属性:
-
标题(title),类型:string | slot,默认 '提示'
-
内容(content),类型:string | slot,默认 ''
-
宽度(width),类型:number,默认 640px
-
高度(height),类型:number,默认 480px
-
是否允许切换全屏,允许后右上角会出现一个按钮(switchFullscreen),类型:boolean,默认 false
-
取消按钮文字(cancelText),类型:string,默认 '取消'
-
确认按钮文字(okText),类型:string,默认 '确认'
-
是否显示底部按钮(footer),类型:boolean,默认 false
-
是否水平垂直居中(center),类型:boolean,默认 true,(false时是固定高度水平居中)
-
固定高度水平居中时,距顶部高度(top),类型:number,默认 100px
-
加载中(loading),类型:boolean,默认 false
-
对话框是否可见(visible),类型:boolean,默认 false
效果如下图:(整体样式模仿ant-design-vue Modal,同时阴影覆盖浏览器窗口)
①创建对话框组件Dialog.vue:
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
const props = defineProps({title: { // 标题 string | slottype: String,default: '提示'},content: { // 内容 string | slottype: String,default: ''},width: { // 宽度,默认640type: Number,default: 640},height: { // 高度,默认480type: Number,default: 480},switchFullscreen: { // 是否允许切换全屏,允许后右上角会出现一个按钮type: Boolean,default: false},cancelText: { // 取消按钮文字type: String,default: '取消'},okText: { // 确认按钮文字type: String,default: '确定'},footer: { // 是否显示底部按钮,默认不显示type: Boolean,default: false},center: { // 水平垂直居中:true 固定高度水平居中:falsetype: Boolean,default: true},top: { // 固定高度水平居中时,距顶部高度type: Number,default: 100},loading: { // 加载中type: Boolean,default: false},visible: { // 对话框是否可见type: Boolean,default: false}})const fullScreen = ref(false)
const dialogWidth = computed(() => {if (fullScreen.value) {return '100%'} else {return props.width + 'px'}})
const dialogHeight = computed(() => {if (fullScreen.value) {return '100vh'} else {return props.height + 'px'}})
watch(() => props.visible, (to) => {if (!to) { // 重置全屏显示fullScreen.value = false}
})
const emits = defineEmits(['close', 'cancel', 'ok'])
function onBlur () {if (!props.loading) {emits('close')}
}
function onFullScreen () {fullScreen.value = !fullScreen.value
}
function onClose () {emits('close')
}
function onCancel () {emits('cancel')
}
function onConfirm () {emits('ok')
}
</script>
<template><Transition><div class="m-dialog-mask" v-show="visible" @click.self="onBlur"><div :class="['m-dialog', center ? 'relative-hv-center' : 'top-center']" :style="`width: ${dialogWidth}; height: ${dialogHeight}; top: ${!center ? top + 'px':'50%'}`"><div class="m-dialog-content" :class="{loading: loading}"><div class="m-spin-dot" v-show="loading"><span class="u-dot-item"></span><span class="u-dot-item"></span><span class="u-dot-item"></span><span class="u-dot-item"></span></div><svg @click="onFullScreen" v-show="!fullScreen&&switchFullscreen" class="u-screen" viewBox="64 64 896 896" data-icon="fullscreen" aria-hidden="true" focusable="false"><path d="M290 236.4l43.9-43.9a8.01 8.01 0 0 0-4.7-13.6L169 160c-5.1-.6-9.5 3.7-8.9 8.9L179 329.1c.8 6.6 8.9 9.4 13.6 4.7l43.7-43.7L370 423.7c3.1 3.1 8.2 3.1 11.3 0l42.4-42.3c3.1-3.1 3.1-8.2 0-11.3L290 236.4zm352.7 187.3c3.1 3.1 8.2 3.1 11.3 0l133.7-133.6 43.7 43.7a8.01 8.01 0 0 0 13.6-4.7L863.9 169c.6-5.1-3.7-9.5-8.9-8.9L694.8 179c-6.6.8-9.4 8.9-4.7 13.6l43.9 43.9L600.3 370a8.03 8.03 0 0 0 0 11.3l42.4 42.4zM845 694.9c-.8-6.6-8.9-9.4-13.6-4.7l-43.7 43.7L654 600.3a8.03 8.03 0 0 0-11.3 0l-42.4 42.3a8.03 8.03 0 0 0 0 11.3L734 787.6l-43.9 43.9a8.01 8.01 0 0 0 4.7 13.6L855 864c5.1.6 9.5-3.7 8.9-8.9L845 694.9zm-463.7-94.6a8.03 8.03 0 0 0-11.3 0L236.3 733.9l-43.7-43.7a8.01 8.01 0 0 0-13.6 4.7L160.1 855c-.6 5.1 3.7 9.5 8.9 8.9L329.2 845c6.6-.8 9.4-8.9 4.7-13.6L290 787.6 423.7 654c3.1-3.1 3.1-8.2 0-11.3l-42.4-42.4z"></path></svg><svg @click="onFullScreen" v-show="fullScreen&&switchFullscreen" class="u-screen" viewBox="64 64 896 896" data-icon="fullscreen-exit" aria-hidden="true" focusable="false"><path d="M391 240.9c-.8-6.6-8.9-9.4-13.6-4.7l-43.7 43.7L200 146.3a8.03 8.03 0 0 0-11.3 0l-42.4 42.3a8.03 8.03 0 0 0 0 11.3L280 333.6l-43.9 43.9a8.01 8.01 0 0 0 4.7 13.6L401 410c5.1.6 9.5-3.7 8.9-8.9L391 240.9zm10.1 373.2L240.8 633c-6.6.8-9.4 8.9-4.7 13.6l43.9 43.9L146.3 824a8.03 8.03 0 0 0 0 11.3l42.4 42.3c3.1 3.1 8.2 3.1 11.3 0L333.7 744l43.7 43.7A8.01 8.01 0 0 0 391 783l18.9-160.1c.6-5.1-3.7-9.4-8.8-8.8zm221.8-204.2L783.2 391c6.6-.8 9.4-8.9 4.7-13.6L744 333.6 877.7 200c3.1-3.1 3.1-8.2 0-11.3l-42.4-42.3a8.03 8.03 0 0 0-11.3 0L690.3 279.9l-43.7-43.7a8.01 8.01 0 0 0-13.6 4.7L614.1 401c-.6 5.2 3.7 9.5 8.8 8.9zM744 690.4l43.9-43.9a8.01 8.01 0 0 0-4.7-13.6L623 614c-5.1-.6-9.5 3.7-8.9 8.9L633 783.1c.8 6.6 8.9 9.4 13.6 4.7l43.7-43.7L824 877.7c3.1 3.1 8.2 3.1 11.3 0l42.4-42.3c3.1-3.1 3.1-8.2 0-11.3L744 690.4z"></path></svg><svg @click="onClose" class="u-close" viewBox="64 64 896 896" data-icon="close" aria-hidden="true" focusable="false"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg><div class="m-dialog-header"><slot name="title"><div class="u-head">{{ title }}</div></slot></div><div class="m-dialog-body" :style="`height: calc(${dialogHeight} - ${footer ? '158px':'103px'});`"><slot>{{ content }}</slot></div><div class="m-dialog-footer" v-show="footer"><button class="u-cancel" @click="onCancel">{{ cancelText }}</button><button class="u-confirm" @click="onConfirm">{{ okText }}</button></div></div></div></div></Transition>
</template>
<style lang="less" scoped>
.v-enter-active, .v-leave-active {transition: opacity 0.3s ease;
}
.v-enter-from, .v-leave-to {opacity: 0;
}
.flex-hv-center { // 水平垂直居中方法①:弹性布局,随内容增大高度,并自适应水平垂直居中display: flex;justify-content: center;align-items: center;
}
.relative-hv-center { // 水平垂直居中方法②:相对定位,随内容增大高度,并自适应水平垂直居中position: relative;top: 50%;transform: translateY(-50%);-ms-transform: translateY(-50%);; /* IE 9 */-webkit-transform: translateY(-50%); /* Safari and Chrome */
}
.top-center { // 相对定位,固定高度,始终距离视图顶端100pxposition: relative;// top: 100px;
}
.m-dialog-mask {position: fixed;top: 0;right: 0;bottom: 0;left: 0;width: 100%;height: 100%;z-index: 10000;background: rgba(0,0,0,0.45);.m-dialog {margin: 0 auto;transition: all .3s ease;.m-spin-dot { // 绝对定位,并设置水平垂直居中position: absolute;display: inline-block;right: 0;left: 0;top: 0;bottom: 0;margin: auto;width: 24px;height: 24px;transform: rotate(45deg);-ms-transform: rotate(45deg); /* Internet Explorer */-moz-transform: rotate(45deg); /* Firefox */-webkit-transform: rotate(45deg); /* Safari 和 Chrome */-o-transform: rotate(45deg); /* Opera */animation: rotate 1.2s linear infinite;-webkit-animation: rotate 1.2s linear infinite;@keyframes rotate {100% {transform: rotate(405deg);}}.u-dot-item { // 单个圆点样式position: absolute;width: 8px;height: 8px;background: @themeColor;border-radius: 50%;opacity: .3;animation: spinMove 1s linear infinite alternate;-webkit-animation: spinMove 1s linear infinite alternate;@keyframes spinMove {100% {opacity: 1;}}}.u-dot-item:first-child {top: 0;left: 0;}.u-dot-item:nth-child(2) {top: 0;right: 0;animation-delay: .4s;-webkit-animation-delay: .4s;}.u-dot-item:nth-child(3) {bottom: 0;right: 0;animation-delay: .8s;-webkit-animation-delay: .8s;}.u-dot-item:last-child {bottom: 0;left: 0;animation-delay: 1.2s;-webkit-animation-delay: 1.2s;}}.loading { // 加载过程背景虚化background: rgb(248, 248, 248) !important;pointer-events: none; // 屏蔽鼠标事件}.m-dialog-content {position: relative;background: #fff;border-radius: 4px;box-shadow: 0 4px 12px rgba(0,0,0,.1);.u-screen {.u-close();right: 64px;}.u-close {width: 16px;height: 16px;position: absolute;top: 19px;right: 24px;fill: rgba(0,0,0,.45);cursor: pointer;transition: fill .3s;&:hover {fill: rgba(0,0,0,.75);}}.m-dialog-header {height: 22px;padding: 16px 24px;color: rgba(0,0,0,.65);border-radius: 4px 4px 0 0;border-bottom: 1px solid #e8e8e8;.u-head {margin: 0;color: rgba(0,0,0,.85);font-weight: 500;font-size: 16px;line-height: 22px;word-wrap: break-word;}}.m-dialog-body {padding: 24px;font-size: 16px;line-height: 1.5;word-wrap: break-word;overflow: auto;transition: all .3s;}.m-dialog-footer {padding: 10px 16px;text-align: right;border-top: 1px solid #e8e8e8;.u-cancel {height: 32px;line-height: 32px;padding: 0 15px;font-size: 16px;border-radius: 4px;color: rgba(0,0,0,.65);background: #fff;border: 1px solid #d9d9d9;cursor: pointer;transition: all .3s cubic-bezier(.645,.045,.355,1);&:hover {color: fade(@themeColor, 80%);border-color: fade(@themeColor, 80%);}&:focus {color: shade(@themeColor, 12%);border-color: shade(@themeColor, 12%);}}.u-confirm {margin-left: 8px;height: 32px;line-height: 32px;padding: 0 15px;font-size: 16px;border-radius: 4px;background: @themeColor;border: 1px solid @themeColor;color: #fff;transition: all .3s cubic-bezier(.645,.045,.355,1);cursor: pointer;&:hover {background: fade(@themeColor, 80%);border-color: fade(@themeColor, 80%);}&:focus {background: shade(@themeColor, 12%);border-color: shade(@themeColor, 12%);}}}}}
}
</style>
②在要使用的页面引入:
<script setup lang="ts">
import { Dialog } from './Dialog.vue'
import { ref } from 'vue'
import { rafTimeout } from '../../packages'const center = ref(true)
const footer = ref(false)
const loading = ref(false)
const visible = ref(false)
const title = ref('Dialog Title')
const content = ref('Content of the modal ...')
function showDialog (info: string) {footer.value = falsecenter.value = truecontent.value = infovisible.value = true
}
function showFooterDialog (info: string) {footer.value = truecenter.value = truecontent.value = infovisible.value = true
}
function showCenterDialog (info: string) {center.value = truecontent.value = infovisible.value = true
}
function showFixDialog (info: string) {center.value = falsecontent.value = infovisible.value = true
}
function onClose () { // 关闭回调visible.value = false
}
function onCancel () { // “取消”按钮回调visible.value = false
}
function onConfirm () { // “确定”,“知道了”按钮回调loading.value = true // 开启加载状态rafTimeout(() => {visible.value = falseloading.value = false}, 500)
}
</script>
<template><div><h2 class="mb10">Dialog 对话框基本使用</h2><Button class="mr30" @click="showDialog('Some descriptions ...')">默认对话框</Button><Button class="mr30" @click="showFooterDialog('Some descriptions ...')">有底部按钮的对话框</Button><Button class="mr30" @click="showCenterDialog('Some descriptions ...')">水平垂直居中对话框</Button><Button class="mr30" @click="showFixDialog('Some descriptions ...')">高度固定对话框</Button><Dialog:title="title":width="720":height="480":content="content":footer="footer"cancelText="取消"okText="确认"switchFullscreen@close="onClose"@cancel="onCancel"@ok="onConfirm":center="center":top="100":loading="loading":visible="visible"><template #title><p class="u-title">Title</p></template><p>Bla bla ...</p><p>Bla bla ...</p><p>Bla bla ...</p></Dialog></div>
</template>
<style lang="less" scoped>
.u-title {font-size: 16px;
}
</style>
相关文章:

Vue3对话框(Dialog)
Vue2对话框(Dialog) 可自定义设置以下属性: 标题(title),类型:string | slot,默认 提示 内容(content),类型:string | slot…...

【深度强化学习】(5) DDPG 模型解析,附Pytorch完整代码
大家好,今天和各位分享一下深度确定性策略梯度算法 (Deterministic Policy Gradient,DDPG)。并基于 OpenAI 的 gym 环境完成一个小游戏。完整代码在我的 GitHub 中获得: https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Mod…...
unity,Color.Lerp函数
介绍 Color.Lerp函数是Unity引擎中的一个静态函数,用于在两个颜色值之间进行线性插值,从而实现颜色渐变效果 方法 Color.Lerp函数是Unity引擎中的一个静态函数,用于在两个颜色值之间进行线性插值,从而实现颜色渐变效果。该函数的…...

洛谷P8799 [蓝桥杯 2022 国 B] 齿轮 C语言/C++
[蓝桥杯 2022 国 B] 齿轮 题目描述 这天,小明在组装齿轮。 他一共有 nnn 个齿轮,第 iii 个齿轮的半径为 rir_{i}ri, 他需要把这 nnn 个齿轮按一定顺序从左到右组装起来,这样最左边的齿轮转起来之后,可以传递到最右边的齿轮&a…...

景区在线售票系统功能开发介绍
目前游客线上订票已经普及,景区开通线上购票渠道,方便游客购票,对于还没有开通线上购票的景区来说,需要提前了解一下景区线上售票系统的一些功能,下面给大家详细介绍一下景区在线售票需要哪些功能。 1、在线售票 包含门…...
webService的底层调用方式
webservice中采用协议Http,是指什么意思 WebService使用的是 SOAP (Simple Object Access Protocol)协议 Soap协议只是用来封装消息用的。封装后的消息你可以通过各种已有的协议来传输,比如http,tcp/ip,smtp,等等,你甚至还一次用自定义的协议…...

关于文件的一些小知识下
🍍个人主页🍍:🔜勇敢的小牛儿🚩 🔱推荐专栏🔱:C语言知识点 ⚠️座右铭⚠️:敢于尝试才有机会 🐒今日鸡汤🐒: 你受的苦 吃的亏 担的责 扛的罪 忍的…...

使用Cheat Engine与DnSpy破解Unity游戏
题目连接: https://play.picoctf.org/practice/challenge/361?originalEvent72&page3我们是windows系统,所以点击windows game下载游戏 双击运行pico.exe 屏幕上方的一串英文是叫我们找flag,我在这个小地图里走来走去也没flagÿ…...

溯源取证-内存取证基础篇
使用工具: volatility_2.6_lin64_standalone 镜像文件: CYBERDEF-567078-20230213-171333.raw 使用环境: kali linux 2022.02 我们只有一个RAW映像文件,如何从该映像文件中提取出我们想要的东西呢? 1.Which volatili…...

Leetcode.100 相同的树
题目链接 Leetcode.100 相同的树 easy 题目描述 给你两棵二叉树的根节点 p和 q,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p [1,2,3…...
每个程序员都应该知道的8大算法
在编程开发中,算法是用于解决特定问题或完成特定任务的一组指令或过程。算法可以用任何编程语言表示,可以像一系列基本操作一样简单,也可以像涉及不同数据结构和逻辑的多步骤过程一样复杂。 算法的主要目标是接收输入、处理它并提供预期的输…...

Nestjs实战超干货-概况-模块-Modules
模块 模块就是一个声明了装饰器Module()的类。装饰器Module()提供了元数据,以便让Nest组织应用程序结构。 每个应用程序至少有一个模块,即根模块。根模块是 Nest 用来构建应用程序图的起点,应用程序图是 Nest 用来解析模块和提供者关系和依赖…...
template
模板 模板注意事项 模板的函数体和声明一定要在一起,即放在同一个.h文件中,而不能将其分开到cpp和h文件中模板的编译技巧就是尽量多编译,模板很难查找错误模板的报错一般只有第一行有作用模板指定类型从左到右依次指定 模板推导 #pragma #…...

innovus中时序路径debug及命令使用详解?
写在前面:发现place结果所有与outport相关的timing check都找不到? 刚开始怀疑是sdc约束问题,check了input sdc文件及enc.dat/mmmc/mode/func.sdc 看一下是否设置了set_false_path.当然也可以用命令报出来: report_timing -unconstrained …...

C语言爱心代码大全集—会Ctrl+C就可以表白了
一、C语言爱心代码大全,会CtrlC就可以表白了! 博主整理了一个C语言爱心代码大全,里面有C语言爱心代码会动的动态效果和C语言爱心代码大全静态效果,只需复制粘贴就可以用啦! 1、动态C语言爱心代码效果图如下ÿ…...

python+vue+django耕地信息管理系统的设计与实现
基普通用户模块含有个人中心、耕地信息管理、转让许可申请管理、租赁许可申请管理等功能;普通管理员模块含有个人中心、用户管理、公示公告管理、耕地信息管理、耕地信息统计、转让许可申请管理、租赁许可申请管理、转让协议管理、租赁协议管理等功能;管…...

【云原生】Dockerfile制作WordPress镜像,实现compose编排部署
文章目录👹 关于作者前言环境准备目录结构dockerfile制作镜像yum 脚本Dockerfile-mariadb 镜像Dockerfile-service 镜像docker compose 编排提升✊ 最后👹 关于作者 大家好,我是秋意临。 😈 CSDN作者主页 😎 博客主页…...

五款好用又有趣的WIN10软件推荐
如果你想让你的电脑使用更方便、更有趣、更专业,那么你一定要看看这篇文章,因为我要给你推荐五款好用又有趣的WIN10软件 1.全局搜索——火柴 火柴是一款全局搜索软件,可以让你快速找到你想要的文件、程序、网页等,只需按下AltSp…...
朴素贝叶斯算法
# -*-coding:utf-8-*- """ Author: sunchang Desc: 代码4-7 朴素贝叶斯实现对异常账户检测 """ import numpy as np class NaiveBayesian: def __init__(self, alpha): self.classP dict() self.classP_f…...

【常见CSS扫盲雪碧图】从源码细看CSS雪碧图原理及实现,千字详解【附源码demo下载】
【写在前面】其实估计很多人都听过雪碧图,或者是CSS-Sprite,在很多门户网站就会经常有用到的,之所有引出雪碧图这个概念还得从前端加载多个图片时候页面闪了一下说起,这样给人的视觉效果体验很差,也就借此机会和大家说…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...