ElementPlus函數(shù)式彈窗調(diào)用的實現(xiàn)
在前端開發(fā)中,彈窗組件是必不可少的交互元素。雖然 ElementPlus 提供了優(yōu)秀的 Dialog 組件,但有時我們需要更靈活、更自定義的調(diào)用方式。本文將介紹如何實現(xiàn)一個類似 ElementPlus 的函數(shù)式彈窗調(diào)用方案,讓你的彈窗使用更加優(yōu)雅便捷。
核心實現(xiàn)
1. 彈窗容器管理 Hook
首先我們創(chuàng)建一個管理彈窗容器和動畫的 Hook:
// useDialog.js
import { render, h } from 'vue'
export function useDialog() {
const div = document.createElement('div')
div.style.display = 'none'
document.body.appendChild(div)
// 進場動畫
setTimeout(() => {
div.style.opacity = '0'
div.style.position = 'fixed'
div.style.zIndex = '2001'
div.style.display = 'initial'
div.style.transition = 'opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
requestAnimationFrame(() => {
div.style.opacity = '1'
})
}, 10)
// 退場動畫
const close = () => {
const bgElement = div.querySelector('.mark-bg')
if (bgElement) {
bgElement.classList.add('closing')
}
setTimeout(() => {
render(null, div)
document.body.removeChild(div)
}, 300)
}
return { div, close }
}
2. 函數(shù)式調(diào)用封裝
// dialogManager.js
import { useDialog } from './useDialog'
export function createDialog(component, props = {}) {
return new Promise((resolve) => {
const { div, close } = useDialog()
const handleConfirm = (data) => {
close()
resolve({ action: 'confirm', data })
}
const handleCancel = () => {
close()
resolve({ action: 'cancel' })
}
const vNode = h(component, {
...props,
onConfirm: handleConfirm,
onCancel: handleCancel
})
render(vNode, div)
})
}
3. 基礎(chǔ)彈窗組件樣式
/* dialog.css */
.mark-bg {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 2000;
display: flex;
justify-content: center;
align-items: center;
transition: opacity 0.3s ease;
}
.mark-bg.closing {
opacity: 0;
}
.base-popup {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
max-width: 80%;
max-height: 80%;
overflow: auto;
}
使用示例
1. 創(chuàng)建自定義彈窗組件
<!-- CustomDialog.vue -->
<template>
<div class="mark-bg" @click.self="$emit('cancel')">
<div class="base-popup">
<h3>自定義彈窗標(biāo)題</h3>
<div class="content">
<!-- 你的自定義內(nèi)容 -->
<p>這是一個自定義彈窗的內(nèi)容</p>
</div>
<div class="footer">
<button @click="$emit('confirm', { data: '示例數(shù)據(jù)' })">確認(rèn)</button>
<button @click="$emit('cancel')">取消</button>
</div>
</div>
</div>
</template>
<script setup>
defineEmits(['confirm', 'cancel'])
</script>
2. 函數(shù)式調(diào)用
import { createDialog } from './dialogManager'
import CustomDialog from './CustomDialog.vue'
// 在任何地方調(diào)用
const openCustomDialog = async () => {
const result = await createDialog(CustomDialog, {
title: '自定義標(biāo)題',
content: '自定義內(nèi)容'
})
if (result.action === 'confirm') {
console.log('用戶確認(rèn)', result.data)
} else {
console.log('用戶取消')
}
}
// 在Vue組件中使用
const handleClick = () => {
openCustomDialog()
}
高級功能擴展
1. 支持傳參和返回值
export function createDialog(component, props = {}) {
return new Promise((resolve) => {
// ...同上
const vNode = h(component, {
...props,
onConfirm: (data) => {
close()
resolve({ action: 'confirm', data })
},
onCancel: (reason) => {
close()
resolve({ action: 'cancel', reason })
}
})
render(vNode, div)
})
}
2. 多個彈窗隊列管理
class DialogManager {
constructor() {
this.queue = []
this.currentDialog = null
}
async open(component, props) {
return new Promise((resolve) => {
this.queue.push({ component, props, resolve })
this.processQueue()
})
}
processQueue() {
if (this.currentDialog || this.queue.length === 0) return
const { component, props, resolve } = this.queue.shift()
this.currentDialog = { component, props, resolve }
const { div, close } = useDialog()
const vNode = h(component, {
...props,
onConfirm: (data) => {
close()
this.currentDialog = null
resolve({ action: 'confirm', data })
this.processQueue()
},
onCancel: (reason) => {
close()
this.currentDialog = null
resolve({ action: 'cancel', reason })
this.processQueue()
}
})
render(vNode, div)
}
}
export const dialogManager = new DialogManager()
優(yōu)勢總結(jié)
- 使用簡單:一行代碼即可調(diào)用彈窗
- 解耦性強:彈窗邏輯與業(yè)務(wù)邏輯完全分離
- 靈活性高:支持任意自定義彈窗內(nèi)容
- 用戶體驗好:內(nèi)置動畫效果,交互流暢
- 易于維護:統(tǒng)一的彈窗管理機制
總結(jié)
通過這種函數(shù)式彈窗調(diào)用方案,我們實現(xiàn)了類似 ElementPlus 的便捷調(diào)用方式,同時保持了高度的自定義靈活性。這種方法特別適合需要頻繁使用彈窗交互的復(fù)雜應(yīng)用,能夠顯著提升開發(fā)效率和用戶體驗,希望這個方案能為你帶來啟發(fā)!
到此這篇關(guān)于ElementPlus函數(shù)式彈窗調(diào)用的實現(xiàn)的文章就介紹到這了,更多相關(guān)ElementPlus函數(shù)式彈窗調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue使用xlsx組件輕松實現(xiàn)Excel導(dǎo)出的完整代碼
在日常開發(fā)中,Excel導(dǎo)出是管理系統(tǒng)的高頻需求,本文手把手教你如何在Vue項目中快速實現(xiàn)Excel導(dǎo)出功能,支持復(fù)雜表格樣式,并附贈性能優(yōu)化方案,需要的朋友可以參考下2025-05-05
關(guān)于Vue.js一些問題和思考學(xué)習(xí)筆記(1)
這篇文章主要為大家分享了關(guān)于Vue.js一些問題和思考的學(xué)習(xí)筆記,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12

