欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ElementPlus el-message-box樣式錯(cuò)位問(wèn)題及解決

 更新時(shí)間:2022年09月02日 11:20:53   作者:小狼子丶  
這篇文章主要介紹了ElementPlus el-message-box樣式錯(cuò)位問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

ElementPlus el-message-box樣式錯(cuò)位

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

錯(cuò)位效果截圖

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.提供一個(gè)函數(shù)用來(lái)展示消息框,這個(gè)函數(shù)提供如標(biāo)題、內(nèi)容等配置參數(shù)
  • 2.消息框出現(xiàn)和消失時(shí)有動(dòng)畫(huà)
  • 3.使用 Promise 獲取消息框的結(jié)果

基本思路

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

createApp

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

const app = createApp(MessageBox, {
?? ?message: 'hello?'
})
// 創(chuàng)建無(wú)父元素的文檔對(duì)象,掛載到 DOM 中后直接調(diào)用 app.unmount() 移除 MessageBox
// 和掛載到 div 的區(qū)別是 MessageBox 不會(huì)作為 div 的子元素
const frg = document.createDocumentFragment()
// app.mount 返回組件實(shí)例
// 組件實(shí)例內(nèi)包含 expose 出來(lái)的方法或者數(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)

可以看到無(wú)論是 createApp 方法還是 h 方法,都可以在第二個(gè)參數(shù)中傳入組件的 props,于是我們可以封裝一個(gè)動(dòng)態(tài)顯示組件的函數(shù),這個(gè)函數(shù)接受組件的 props。但是在封裝函數(shù)之前,讓我們先來(lái)實(shí)現(xiàn)

MessageBox 這個(gè)組件

MessageBox 組件實(shí)現(xiàn)

直接貼代碼,講下最關(guān)鍵的幾點(diǎn):

進(jìn)入退出動(dòng)態(tài)效果實(shí)現(xiàn)

設(shè)置一個(gè) transition flag,初始時(shí)為 false,組件 mounted 后 flag 為 true。

全局遮罩層

一個(gè) 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ù)式組件

// 第一個(gè)參數(shù)是 props,第二個(gè)參數(shù)是 context,類(lèi)似 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)
? ? }
})

通過(guò)組件的 props 傳入回調(diào),實(shí)現(xiàn)按鈕點(diǎn)擊事件的傳遞、MessageBox 關(guān)閉時(shí)取消掛載的操作。

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

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。 

相關(guān)文章

最新評(píng)論