ElementPlus el-message-box样式错位问题及解决

目录
  • ElementPlus el-message-box样式错位
    • 解决方案
  • 实现ElementPlus的MessageBox
    • ElementPlus 的 MessageBox 主要功能分析
    • 基本思路
    • MessageBox 组件实现
    • 封装 MessageBox 显示函数

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 选项。

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

(0)

相关推荐

  • 关于Element-ui中el-table出现的表格错位问题解决

    目录 前言 1.数据更新后出现的错位问题 1.1 直接在数据赋值后执行doLayout方法 1.2在生命周期updated里执行doLayout方法 2.浏览器窗口大小变化时出现的错位问题 3.当有多个Tab标签时,切换标签出现的错位问题 3.1 在组件守卫beforeRouteEnter里执行doLayout方法 3.2 如果使用了keep-alive,可以在activated里执行doLayout方法 3.3 也可以通过监听路由,在watch里执行doLayout方法 附:解决element

  • element-plus按需引入后ElMessage与ElLoading在页面中的使用

    目录 element-plus按需引入后ElMessage与ElLoading在页面使用 按照官网按需引用element-plus ElMessage与ElLoading使用问题 解决找不到名称“ElMessage”报错 虽然在main.ts中引入可以解决 从element-plus引入ElLoading和ILoadingInstance出现错误 找了一早上的bug终于解决了 element-plus按需引入后ElMessage与ElLoading在页面使用 按照官网按需引用element-pl

  • Vue3.0之引入Element-plus ui样式的两种方法

    目录 第一种:CDN 第二种:通过 npm 安装,并希望配合 webpack 使用 安装:官网欢迎star:github npm install element-plus --save 第一种:CDN 目前可以通过 unpkg.com/element-plus 获取到最新版本的资源,在页面上引入 js 和 css 文件即可开始使用.<! – 引入样式 -->< link rel=“stylesheet” href=“https://unpkg.com/element-plus/lib/t

  • vue中element组件样式修改无效的解决方法

    如下所示: <style> .detail{ .el-input__inner { height: 48px; } } </style> 直接写style注意不加scoped,然后用一个组件最外层的class包裹住,就不会改到所有的组件的样式了. 以上这篇vue中element组件样式修改无效的解决方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们. 您可能感兴趣的文章: Vue 组件间的样式冲突污染 浅谈vue中改elementUI默认样式引发的st

  • ElementPlus el-message-box样式错位问题及解决

    目录 ElementPlus el-message-box样式错位 解决方案 实现ElementPlus的MessageBox ElementPlus 的 MessageBox 主要功能分析 基本思路 MessageBox 组件实现 封装 MessageBox 显示函数 ElementPlus el-message-box样式错位 不知道从哪个版本开始发现,element-plus的message-box在有图标的时候,错位比较严重,f12跟官网的样式对比后发现,好家伙!原来position:

  • vue3中实现使用element-plus调用message

    目录 vue3使用element-plus调用message 1. 全局引入element之后 2. 在Composition API中setup方法传入了两个变量 3. 还有一种方法是使用 provide/inject 4. 在Composition api中最简单的写法就是按需引入 vue使用Element的message组件 vue3使用element-plus调用message 环境:vue3+typescript+element-plus 1. 全局引入element之后 elemen

  • element-plus 在vue3 中不生效的原因解决方法(element-plus引入)

    目录 1.安装element-plus (3种方式 ) 2. 在main.js种引用 原因一 原因二 vue3.0 不兼容 element-ui ,于是推出了element-plus 1.安装element-plus (3种方式 ) npm install element-plus --save (推荐)yarn add element-pluspnpm install element-plus 2. 在main.js种引用 import 'element-plus/theme-chalk/in

  • jQuery niceScroll滚动条错位问题的解决方法

    虽然niceScroll插件很好用,毕竟它不依赖css,只是单纯的js就可以设置出好看的滚动条了. 最近在项目中使用到niceScroll,而且在表格里有横滚动条,竖滚动条时很容易错位,就是滚动条会悬浮在半空,并不是在div的底部或右边,打开f12可看到滚动条并不是直接定位在div里面,而是在整个body最后,和要使用定位的div同级,这而导致了这个bug,尤其是在IE下更明显,滚动条四处飞︿( ̄︶ ̄)︿. 在网上找了很多资料好像都没有这个情况,可能他们项目没那么多横向滚动条吧..... 要解决

  • Vue打包部署到Nginx时,css样式不生效的解决方式

    今天在将使用Vue-cli编写的前端项目部署到Nginx的时候发生了一件很困扰的问题: Vue-cli项目在本地 使用 npm run dev的时候,页面样式是可以正常加载出来的,但是我将Vue-cli项目通过npm run build 打包生成的 dist 目录部署到Nginx之后,通过访问是无法加载出来样式的. 于是乎,在网上开始寻找资料,发现大部分前辈的解决方案都是在,config的文件夹中的index.js assetsRoot: path.resolve(__dirname, '../

  • elementui的el-popover修改样式不生效的解决

    在使用element-ui的时候,有一个常用的组件,那就是el-popover,但是element-ui官方文档中样式跟用法都比较局限,在使用时都需要改动样式 项目中使用了el-popover,但是想修改一下样式,一直不成功,先来看一下官方文档怎么说的 添加一个类名,string类型,ok,添加一个 <el-popover placement="right" width="400" trigger="hover" popper-class=

  • 小程序自定义组件全局样式不生效的解决方法

    目录 太长不看版 组件样式隔离 demo 试验 优先级 页面的隔离配置 参考资料 在使用原生框架开发小程序时遇到一个问题,在 app.wxss 中定义的全局样式在自定义组件中不生效.后来发现是由于小程序组件样式隔离的配置导致的. 太长不看版 在组件的 json 文件中添加如下配置,全局样式即可生效. // component.json "styleIsolation": "apply-shared" 如果偏好在 js 文件中进行配置,或版本号 < 2.10.1

  • vue 组件中添加样式不生效的解决方法

    如何产生 在开发项目中遇到在组件中添加样式不生效的情况.具体场景如下 //// vue 组件 <template> <div class="box" data-v-33f8ed40></div> <template> //我用js在上面div标签中插入一个<p class='text'>text goes here</p> <script> export default { ... mounted(){

  • element-ui自定义message-box自定义样式不生效的解决

    目录 element-ui自定义message-box自定义样式不生效 背景 先分析下不生效的原因 解决方法 element-ui修改样式不生效,最简单的解决 element-ui自定义message-box自定义样式不生效 背景 这是小伙伴今天在开发中遇到的问题,使用jsx语法自定义一个msgbox,自定义msgbox自然需要自定义样式,然后就遇到了自定义customClass不生效的问题. 下面上jsx的一个写法 this.$msgbox({         title: '确认',    

随机推荐