溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ElementPlus?el-message-box樣式錯位問題如何解決

發(fā)布時間:2022-09-05 10:01:29 來源:億速云 閱讀:572 作者:iii 欄目:開發(fā)技術

本篇內容介紹了“ElementPlus el-message-box樣式錯位問題如何解決”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

ElementPlus el-message-box樣式錯位

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

錯位效果截圖

ElementPlus?el-message-box樣式錯位問題如何解決

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

ElementPlus?el-message-box樣式錯位問題如何解決

本地項目代碼截圖

ElementPlus?el-message-box樣式錯位問題如何解決

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

解決方案

修改css樣式

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

完成效果截圖

ElementPlus?el-message-box樣式錯位問題如何解決

實現(xiàn)ElementPlus的MessageBox

ElementPlus 的 MessageBox 主要功能分析

  • 1.提供一個函數(shù)用來展示消息框,這個函數(shù)提供如標題、內容等配置參數(shù)

  • 2.消息框出現(xiàn)和消失時有動畫

  • 3.使用 Promise 獲取消息框的結果

基本思路

Vue 中動態(tài)顯示一個組件,無非就是通過 h 函數(shù)創(chuàng)建 VNode,并且把這個 VNode 掛載在 DOM 樹上。這里有兩種掛載的方式:

createApp

在 main.js 中創(chuàng)建 Vue 實例用的就是這種方法,這也是 Vue3 中代替 Vue2 的 Vue.extend 的方法,簡單使用案例如下:

const app = createApp(MessageBox, {
    message: 'hello?'
})
// 創(chuàng)建無父元素的文檔對象,掛載到 DOM 中后直接調用 app.unmount() 移除 MessageBox
// 和掛載到 div 的區(qū)別是 MessageBox 不會作為 div 的子元素
const frg = document.createDocumentFragment()
// app.mount 返回組件實例
// 組件實例內包含 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ù)之前,讓我們先來實現(xiàn)

MessageBox 這個組件

MessageBox 組件實現(xiàn)

直接貼代碼,講下最關鍵的幾點:

進入退出動態(tài)效果實現(xiàn)

設置一個 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
// 可以導出或者直接在組件內部使用
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 傳入回調,實現(xiàn)按鈕點擊事件的傳遞、MessageBox 關閉時取消掛載的操作。

另外可以通過 MessageBox.prompt 等靜態(tài)方法直接調用對應 type 的 MessageBox,實現(xiàn)方式是在 MessageBox 上掛上對應的靜態(tài)方法,并且覆蓋 options 的 type 選項。

“ElementPlus el-message-box樣式錯位問題如何解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注億速云網(wǎng)站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI