vue3.2+ts实现在方法中可调用的拟态框弹窗(类el-MessageBox)
公司UI设计的拟态框弹窗跟Element Plus UI的布局不太一致。导致不能够直接修改样式得到想到样式。直接上图。
这个需求最主要的是要通过方法去调用。为了像el-messagebox使用那样方便。能直接在方法中调用。但这也是难点。去查看了element源码,一个套一个的方法 实在看不懂。因为vue2和vue3的机制改动了。vue2的引用方式不适用了。查找了n篇文章,最终在一篇中找到了一个关键点,也可能是错误的方式,但是能用。
import { createApp } from 'vue' import MessageBoxVue from './MessageBox.vue' \\你写的拟态框样式 export const MessageBox = (text: any) => { return new Promise((resolve, reject) => { const capp = createApp(MessageBoxVue, text) const container = document.createElement('div') const instance = capp.mount(container) document.body.insertBefore(container, document.body.firstChild)//插入到body最前面,层级更高 instance.callback = (val: any) => { if (val) { resolve(val) } else { reject() } capp.unmount()//注销 document.body.removeChild(container)//点击后清除弹窗 } instance.close = () => { capp.unmount() document.body.removeChild(container) } }) }
//重点在这儿 //这边相当于把数据当方法使了。我也不知道什么原理。在上面那边就是能接收到回调。 const cancel = () => { callback.value(false) } const confirm = () => { callback.value(true) } const closeBox = () => { close.value() } //抛出这两个方法?反正这个方法不可或缺。 defineExpose({ callback, close })
\\这一段是上面的那个messagebox <template> <div ref="MessageBox" class="message-box" :style="[messageBoxWrapperStyleStyle]"> <div class="message-box-icon"> <i class="iconfont" :style="`color:${iconColor}`" v-html="iconType"></i> </div> <div class="message-box-container"> <div class="message-box-title">{{ title }}</div> <div v-if="isHtml" v-html="content"></div> <p v-else class="message-box-content">{{ content }}</p> <div class="message-box-btn"> <span v-if="isCancel" class="cancel" @click="cancel">{{ cancelVal }}</span> <span v-if="isConfirm" class="confirm" @click="confirm">{{ confirmVal }}</span> </div> </div> <i v-if="closeIcon" class="iconfont cencel-box" @click="closeBox"></i> </div> </template> <script setup lang="ts"> import { computed, CSSProperties, ref } from 'vue' const props = defineProps({ type: { type: String, default: 'warning' }, title: { type: String, default: '' }, content: { type: String, default: '' }, isHtml: { type: Boolean, default: false }, width: { type: Number, default: 416 }, isCancel: { type: Boolean, default: true }, cancelVal: { type: String, default: '取消' }, confirmVal: { type: String, default: '确定' }, isConfirm: { type: Boolean, default: true }, closeIcon: { type: Boolean, default: false } }) const callback = ref() const close = ref() const cw = document.documentElement.clientWidth const ch = document.documentElement.clientHeight // eslint-disable-next-line vue/return-in-computed-property const iconType = computed(() => { switch (props.type) { case 'warning': return '' case 'info': return '' case 'error': return '' case 'success': return '' } }) // eslint-disable-next-line vue/return-in-computed-property const iconColor = computed(() => { switch (props.type) { case 'warning': return '#FF7402' case 'info': return '#0C64EB' case 'error': return '#FF4D4F' case 'success': return '#36B23B' } }) const messageBoxWrapperStyleStyle = computed<CSSProperties>(() => { return { top: `${ch / 2 - 200 > 200 ? ch / 2 - 200 : 200}px`, left: `${cw / 2 - props.width / 2}px`, width: `${props.width}px` } }) const cancel = () => { callback.value(false) } const confirm = () => { callback.value(true) } const closeBox = () => { close.value() } defineExpose({ callback, close }) </script> <style lang="scss" scoped> .cencel-box { position: absolute; top: 15px; right: 20px; cursor: pointer; } .message-box { position: absolute; border-radius: 5px; z-index: 2001; display: flex; background: #ffffff; padding: 20px 20px 20px 32px; box-shadow: 0px 0px 20px 0px rgba(6, 0, 1, 0.1); .message-box-icon { margin-right: 12px; line-height: 38px; .iconfont { font-size: 25px; } } .message-box-container { width: calc(100% - 25px); .message-box-title { font-size: 16px; color: #333333; line-height: 38px; } .message-box-content { margin: 10px 0px 20px; font-size: 14px; min-height: 48px; color: #999999; line-height: 18px; // letter-spacing: 0.5px; } } .message-box-btn { float: right; .cancel { height: 32px; line-height: 30px; display: inline-block; text-align: center; width: 90px; box-sizing: border-box; border: 1px solid #d9d9d9; border-radius: 3px; color: #333333; cursor: pointer; } .cancel:hover { color: #0c64eb; border-color: #0c64eb; } .confirm { height: 32px; width: 90px; display: inline-block; text-align: center; line-height: 32px; margin-left: 10px; background-color: #0c64eb; border-radius: 3px; color: #ffffff; cursor: pointer; } .confirm:hover { background-color: #2373eb; } } } </style>
引入全局后的调用
// 使用: // 在main.ts全局引入,也可以按需引入这里展示全局引入 import {MessageBox} from 'base/src/components/MessageBox/index' // 注册: app.config.globalProperties.$messageBox = MessageBox // 引用: import { getCurrentInstance } from 'vue' const { proxy } = getCurrentInstance() const fn = ()=>{ proxy .$messageBox({ //这边就是传你在MessageBox的props定义的父传子的数据了 title: '是否确定编辑/删除数据?', content: '作业已经发布,如果重新编辑/删除,会清空所有学生 作业提交状态请谨慎操作!' }) .then(() => { console.log(1234) }) .catch(() => { console.log(12345) }) }
到此这篇关于vue3.2+ts实现在方法中可调用的拟态框弹窗(类el-MessageBox)的文章就介绍到这了,更多相关vue3.2+ts实现拟态框弹窗内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
vue elementUI table表格自定义样式滚动效果
这篇文章主要介绍了vue elementUI table表格自定义样式滚动效果,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧2024-08-08vue 动态组件(component :is) 和 dom元素限制(is)用法说明
这篇文章主要介绍了vue 动态组件(component :is) 和 dom元素限制(is)用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-09-09把vue-router和express项目部署到服务器的方法
下面小编就为大家分享一篇把vue-router和express项目部署到服务器的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2018-02-02vue 关闭浏览器窗口的时候,清空localStorage的数据示例
今天小编就为大家分享一篇vue 关闭浏览器窗口的时候,清空localStorage的数据示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2019-11-11
最新评论