vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > ElementPlus函数式弹窗调用

ElementPlus函数式弹窗调用的实现

作者:_AaronWong

在前端开发中,弹窗组件是必不可少的交互元素,本文就来详细的介绍一下ElementPlus函数式弹窗调用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在前端开发中,弹窗组件是必不可少的交互元素。虽然 ElementPlus 提供了优秀的 Dialog 组件,但有时我们需要更灵活、更自定义的调用方式。本文将介绍如何实现一个类似 ElementPlus 的函数式弹窗调用方案,让你的弹窗使用更加优雅便捷。

核心实现

1. 弹窗容器管理 Hook

首先我们创建一个管理弹窗容器和动画的 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. 函数式调用封装

// 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. 基础弹窗组件样式

/* 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. 创建自定义弹窗组件

<!-- CustomDialog.vue -->
<template>
    <div class="mark-bg" @click.self="$emit('cancel')">
        <div class="base-popup">
            <h3>自定义弹窗标题</h3>
            <div class="content">
                <!-- 你的自定义内容 -->
                <p>这是一个自定义弹窗的内容</p>
            </div>
            <div class="footer">
                <button @click="$emit('confirm', { data: '示例数据' })">确认</button>
                <button @click="$emit('cancel')">取消</button>
            </div>
        </div>
    </div>
</template>

<script setup>
defineEmits(['confirm', 'cancel'])
</script>

2. 函数式调用

import { createDialog } from './dialogManager'
import CustomDialog from './CustomDialog.vue'

// 在任何地方调用
const openCustomDialog = async () => {
    const result = await createDialog(CustomDialog, {
        title: '自定义标题',
        content: '自定义内容'
    })
    
    if (result.action === 'confirm') {
        console.log('用户确认', 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()

优势总结

  1. 使用简单:一行代码即可调用弹窗
  2. 解耦性强:弹窗逻辑与业务逻辑完全分离
  3. 灵活性高:支持任意自定义弹窗内容
  4. 用户体验好:内置动画效果,交互流畅
  5. 易于维护:统一的弹窗管理机制

总结

通过这种函数式弹窗调用方案,我们实现了类似 ElementPlus 的便捷调用方式,同时保持了高度的自定义灵活性。这种方法特别适合需要频繁使用弹窗交互的复杂应用,能够显著提升开发效率和用户体验,希望这个方案能为你带来启发!

到此这篇关于ElementPlus函数式弹窗调用的实现的文章就介绍到这了,更多相关ElementPlus函数式弹窗调用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文