ElementPlus el-message-box樣式錯位問題及解決
ElementPlus el-message-box樣式錯位
不知道從哪個版本開始發(fā)現(xiàn),element-plus的message-box在有圖標(biāo)的時候,錯位比較嚴(yán)重,f12跟官網(wǎng)的樣式對比后發(fā)現(xiàn),好家伙!原來position: absolute被覆蓋了。
錯位效果截圖

ElementPlus官網(wǎng)代碼截圖

本地項(xiàng)目代碼截圖

可以看出在本地中el-message-box__status樣式的position并未生效
解決方案
修改css樣式
.el-message-box__status {
position: absolute !important;
}完成效果截圖

實(shí)現(xiàn)ElementPlus的MessageBox
ElementPlus 的 MessageBox 主要功能分析
- 1.提供一個函數(shù)用來展示消息框,這個函數(shù)提供如標(biāo)題、內(nèi)容等配置參數(shù)
- 2.消息框出現(xiàn)和消失時有動畫
- 3.使用 Promise 獲取消息框的結(jié)果
基本思路
Vue 中動態(tài)顯示一個組件,無非就是通過 h 函數(shù)創(chuàng)建 VNode,并且把這個 VNode 掛載在 DOM 樹上。這里有兩種掛載的方式:
createApp
在 main.js 中創(chuàng)建 Vue 實(shí)例用的就是這種方法,這也是 Vue3 中代替 Vue2 的 Vue.extend 的方法,簡單使用案例如下:
const app = createApp(MessageBox, {
?? ?message: 'hello?'
})
// 創(chuàng)建無父元素的文檔對象,掛載到 DOM 中后直接調(diào)用 app.unmount() 移除 MessageBox
// 和掛載到 div 的區(qū)別是 MessageBox 不會作為 div 的子元素
const frg = document.createDocumentFragment()
// app.mount 返回組件實(shí)例
// 組件實(shí)例內(nèi)包含 expose 出來的方法或者數(shù)據(jù)
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 方法,都可以在第二個參數(shù)中傳入組件的 props,于是我們可以封裝一個動態(tài)顯示組件的函數(shù),這個函數(shù)接受組件的 props。但是在封裝函數(shù)之前,讓我們先來實(shí)現(xiàn)
MessageBox 這個組件
MessageBox 組件實(shí)現(xiàn)
直接貼代碼,講下最關(guān)鍵的幾點(diǎn):
進(jìn)入退出動態(tài)效果實(shí)現(xiàn)
設(shè)置一個 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>函數(shù)式組件
// 第一個參數(shù)是 props,第二個參數(shù)是 context,類似 setup 的參數(shù)
// 返回值為 VNode
// 可以導(dǎo)出或者直接在組件內(nèi)部使用
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 顯示函數(shù)
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 傳入回調(diào),實(shí)現(xiàn)按鈕點(diǎn)擊事件的傳遞、MessageBox 關(guān)閉時取消掛載的操作。
另外可以通過 MessageBox.prompt 等靜態(tài)方法直接調(diào)用對應(yīng) type 的 MessageBox,實(shí)現(xiàn)方式是在 MessageBox 上掛上對應(yīng)的靜態(tài)方法,并且覆蓋 options 的 type 選項(xiàng)。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue導(dǎo)出excel多層表頭的實(shí)現(xiàn)方案詳解
這篇文章主要為大家詳細(xì)介紹了vue導(dǎo)出excel多層表頭的實(shí)現(xiàn)方案,文中的示例代碼簡潔易懂,具有一定的借鑒價值,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-04-04
Vue Computed中g(shù)et和set的用法及Computed與watch的區(qū)別
這篇文章主要介紹了Vue Computed中g(shù)et和set的用法及Computed與watch的區(qū)別,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11
Vue項(xiàng)目線上更新無需強(qiáng)制刷新的幾種實(shí)現(xiàn)方案(無感更新)
在 Vue 項(xiàng)目中,當(dāng)發(fā)布新版本后,用戶可能因?yàn)闉g覽器緩存而繼續(xù)使用舊版本,所以本文給大家介紹了Vue 項(xiàng)目線上更新無需強(qiáng)制刷新的幾種實(shí)現(xiàn)方案,并通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下2025-03-03
Vue實(shí)現(xiàn)鼠標(biāo)懸浮隱藏與顯示圖片效果@mouseenter和@mouseleave事件詳解
在所做的Vue項(xiàng)目中,有時候需要在鼠標(biāo)移動文字框的時候顯示一些詳細(xì)信息,下面這篇文章主要給大家介紹了關(guān)于Vue實(shí)現(xiàn)鼠標(biāo)懸浮隱藏與顯示圖片效果@mouseenter和@mouseleave事件的相關(guān)資料,需要的朋友可以參考下2022-11-11
vue3網(wǎng)絡(luò)請求添加loading過程
這篇文章主要介紹了vue3網(wǎng)絡(luò)請求添加loading過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08

