ElementPlus el-message-box样式错位

不知道从哪个版本开始发现,element-plus的message-box在有图标的时候,错位比较严重,f12跟官网的样式对比后发现,好家伙!原来position: absolute被覆盖了。

错位效果截图

ElementPlus官网代码截图

本地项目代码截图

可以看出在本地中el-message-box__status样式的position并未生效

解决方案

修改css样式

.el-message-box__status {
  position: absolute !important;
}

完成效果截图

实现ElementPlus的MessageBox

ElementPlus 的 MessageBox 主要功能分析

  • 1.提供一个函数用来展示消息框,这个函数提供如标题、内容等配置参数
  • 2.消息框出现和消失时有动画
  • 3.使用 Promise 获取消息框的结果

基本思路

Vue 中动态显示一个组件,无非就是通过 h 函数创建 VNode,并且把这个 VNode 挂载在 DOM 树上。这里有两种挂载的方式:

createApp

在 main.js 中创建 Vue 实例用的就是这种方法,这也是 Vue3 中代替 Vue2 的 Vue.extend 的方法,简单使用案例如下:

const app = createApp(MessageBox, {
    message: 'hello?'
})
// 创建无父元素的文档对象,挂载到 DOM 中后直接调用 app.unmount() 移除 MessageBox
// 和挂载到 div 的区别是 MessageBox 不会作为 div 的子元素
const frg = document.createDocumentFragment()
// app.mount 返回组件实例
// 组件实例内包含 expose 出来的方法或者数据
const vm = app.mount(frg)
document.body.appendChild(frg)

h render

和 createApp 方法大同小异

const vn = h(MessageBox, {
    message: 'vnode'
})
render(vn, container)
document.body.appendChild(container)

可以看到无论是 createApp 方法还是 h 方法,都可以在第二个参数中传入组件的 props,于是我们可以封装一个动态显示组件的函数,这个函数接受组件的 props。但是在封装函数之前,让我们先来实现

MessageBox 这个组件

MessageBox 组件实现

直接贴代码,讲下最关键的几点:

进入退出动态效果实现

设置一个 transition flag,初始时为 false,组件 mounted 后 flag 为 true。

全局遮罩层

一个 fixed 定位宽高为100%的 div。

剩下的主要看 script 部分

<template>
    <transition name="messagebox-fade" @after-leave="onDestroy">
        <div @click="setVisiable(false)" v-show="visiable"
            class="z-50 flex items-center justify-center fixed top-0 left-0 w-full h-full bg-dark-50/50">
            <div @click.stop class="transform -translate-y-1/2 p-2 rounded min-w-3/7 bg-white">
                <p class="text-sm text-gray-600 font-light"> {{ title }}</p>
                <p class="my-4 text-lg">
                    <content-view :type="type"></content-view>
                </p>
                <div class="w-full flex justify-end items-center">
                    <button @click="okBtnClicked" class="btn btn-primary"> {{ ok }}</button>
                    <button @click="cancelBtnClicked" v-if="cancel" class="ml-2 btn btn-danger"> {{ cancel }}</button>
                </div>
            </div>
        </div>
    </transition>
</template>
<script setup>
import { ref, onMounted, h } from 'vue'
const { onOK, onCancel, message } = defineProps({
    title: {
        type: String,
        default: '提示'
    },
    message: {
        type: String,
        default: ''
    },
    type: {
        type: String,
        validator: (value) => {
            return ['confirm', 'prompt'].includes(value)
        }
    },
    ok: {
        type: String,
        default: 'OK'
    },
    cancel: {
        type: String,
        default: ''
    },
    onDestroy: Function,
    onOK: Function,
    onCancel: Function
})
const promptContent = ref('')
const ContentView = ({ type }) => {
    switch (type) {
        case (!type || 'confirm'):
            return h('p', null, message)
        case 'prompt':
            return h('input', {
                class: 'messagebox-input',
                onInput: (e) => promptContent.value = e.target.value
            })
    }
}
const visiable = ref(false);
const setVisiable = (vis) => {
    visiable.value = vis;
}
const okBtnClicked = () => {
    setVisiable(false);
    onOK(promptContent.value)
}
const cancelBtnClicked = () => {
    setVisiable(false)
    onCancel()
}
onMounted(() => {
    setVisiable(true);
})
</script>
<style scoped>
.btn {
    @apply outline-gray-100 border-none p-1 rounded bg-warm-gray-200
}
.btn-primary {
    @apply bg-sky-300
}
.messagebox-input {
    @apply border rounded border-light-900 outline-none w-full py-1 px-2 text-lg 
}
.messagebox-fade-enter-from,
.messagebox-fade-leave-to {
    @apply opacity-0
}
.messagebox-fade-enter-active,
.messagebox-fade-leave-active {
    @apply transition-opacity
}
</style>

函数式组件

// 第一个参数是 props,第二个参数是 context,类似 setup 的参数
// 返回值为 VNode
// 可以导出或者直接在组件内部使用
const ContentView = ({ type }) => {
    switch (type) {
        case (!type || 'confirm'):
            return h('p', null, message)
        case 'prompt':
            return h('input', {
                class: 'messagebox-input',
                onInput: (e) => promptContent.value = e.target.value
            })
    }
}

封装 MessageBox 显示函数

import { createApp } from 'vue'
import MessageBoxCpn from './MessageBox.vue'
const fields = ['confirm', 'prompt']
export default function MessageBox(options) {
    return new Promise((resolve, reject) => {
        const app = createApp(MessageBoxCpn, {
            ...options,
            onDestroy: () => {
                app.unmount()
            },
            onOK: (value) => {
                resolve(value)
            },
            onCancel: () => {
                reject()
            }
        })
        const frg = document.createDocumentFragment()
        app.mount(frg)
        document.body.appendChild(frg)
    })
}
fields.forEach(field => {
    MessageBox[field] = (options) => {
        options.type = field
        return MessageBox(options)
    }
})

通过组件的 props 传入回调,实现按钮点击事件的传递、MessageBox 关闭时取消挂载的操作。

另外可以通过 MessageBox.prompt 等静态方法直接调用对应 type 的 MessageBox,实现方式是在 MessageBox 上挂上对应的静态方法,并且覆盖 options 的 type 选项。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持Devmax。 

ElementPlus el-message-box样式错位问题及解决的更多相关文章

  1. jQuery zTree如何改变指定节点文本样式

    这篇文章主要介绍了jQuery zTree如何改变指定节点文本样式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

  2. PHP导出带样式的Excel示例代码

    相信大家在工作的时候有客户会向你抱怨,软件为他们导出的Excel格式太难看了,这个时候我们就需要到处自定义样式的Excel了,那么或许这篇文章会对你有所帮助,有需要的可以参考借鉴。

  3. Ant Design Vue 修改表格头部样式的详细代码

    这篇文章主要介绍了Ant Design Vue 修改表格头部样式,首先用到的是customHeaderRow这个API,类型是一个函数,本文通过完整代码给大家详细讲解,需要的朋友可以参考下

  4. vue中vant组件样式失效问题及解决

    这篇文章主要介绍了vue中vant组件样式失效问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  5. JS样式获取的封装方法实例详解

    这篇文章主要介绍了JS样式获取的封装方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. HTML5实现留言和回复页面样式

    这篇文章主要介绍了用HTML5如何实现留言和回复样式,需要的朋友可以参考下

  7. js改变css样式的三种方法推荐

    下面小编就为大家带来一篇js改变css样式的三种方法推荐。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  8. 【经典源码收藏】jQuery实用代码片段(筛选,搜索,样式,清除默认值,多选等)

    这篇文章主要介绍了jQuery实用代码片段,包括筛选,搜索,样式,清除默认值,多选等多种功能.具有一定参考借鉴价值,需要的朋友可以参考下

  9. Vue的样式绑定详解

    这篇文章主要为大家详细介绍了Vue的样式绑定,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  10. Python实现Word文档样式批量处理

    这篇文章主要为大家详细介绍了如何利用Python中的python-docx非标准库实现word文档样式批量处理,文中示例代码讲解详细,感兴趣的可以了解一下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部