当前位置: 首页 > news >正文

vue3 函数式弹窗

在 Vue 3 中,函数式弹窗是一种常见的需求,尤其是在需要动态创建和销毁组件时(例如消息提示框、确认框等)。Vue 3 提供了强大的 Composition API 和 createVNode 等工具,使得实现函数式弹窗变得非常灵活。

以下是实现函数式弹窗的核心思路和步骤:


1. 核心思路

函数式弹窗的核心是通过编程方式动态挂载一个组件到 DOM 中,而不需要手动在模板中声明。这通常包括以下步骤:

  1. 定义弹窗组件:创建一个独立的弹窗组件。
  2. 动态挂载组件:使用 Vue 的 createVNoderender 方法将组件挂载到指定的 DOM 节点。
  3. 提供关闭功能:在弹窗组件中提供关闭逻辑,并通过回调或 Promise 返回用户操作结果。
  4. 清理挂载节点:在弹窗关闭后,移除组件实例以避免内存泄漏。

2. 实现步骤

(1) 定义弹窗组件

首先,创建一个简单的弹窗组件,例如 Modal.vue

<template>
  <div class="modal-overlay" @click.self="close">
    <div class="modal-content">
      <h3>{{ title }}</h3>
      <p>{{ content }}</p>
      <button @click="confirm">确认</button>
      <button @click="close">取消</button>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  props: {
    title: String,
    content: String,
  },
  emits: ['close', 'confirm'],
  setup(props, { emit }) {
    const close = () => {
      emit('close');
    };

    const confirm = () => {
      emit('confirm');
      close();
    };

    return { close, confirm };
  },
};
</script>

<style scoped>
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
}

.modal-content {
  background: white;
  padding: 20px;
  border-radius: 8px;
  text-align: center;
}
</style>

(2) 创建函数式调用方法

接下来,编写一个函数来动态挂载和卸载弹窗组件:

import { createVNode, render } from 'vue';
import Modal from './Modal.vue';

// 动态创建弹窗的函数
function createModal(options) {
  return new Promise((resolve, reject) => {
    // 创建一个容器元素
    const container = document.createElement('div');
    document.body.appendChild(container);

    // 创建 VNode
    const vnode = createVNode(Modal, {
      ...options,
      onClose: () => {
        // 清理组件
        render(null, container);
        document.body.removeChild(container);
        resolve(false); // 用户取消
      },
      onConfirm: () => {
        // 清理组件
        render(null, container);
        document.body.removeChild(container);
        resolve(true); // 用户确认
      },
    });

    // 挂载组件
    render(vnode, container);
  });
}

export default createModal;

(3) 使用函数式弹窗

现在可以在任何地方调用 createModal 函数来显示弹窗:

import createModal from './createModal';

async function showCustomModal() {
  const result = await createModal({
    title: '提示',
    content: '确定要执行此操作吗?',
  });

  if (result) {
    console.log('用户点击了确认');
  } else {
    console.log('用户点击了取消');
  }
}

// 调用示例
showCustomModal();

3. 实现细节解析

(1) 动态挂载组件
  • createVNode:用于创建虚拟 DOM 节点。
  • render:将虚拟 DOM 渲染到指定的 DOM 容器中。
  • 在组件销毁时,调用 render(null, container) 清空挂载点的内容。
(2) 异步控制
  • 使用 Promise 包装弹窗逻辑,便于在用户操作完成后返回结果。
  • resolvereject 分别对应用户确认和取消的操作。
(3) 避免内存泄漏
  • 在弹窗关闭后,确保从 DOM 中移除挂载的容器,避免残留节点导致内存泄漏。

4. 可选优化

(1) 全局注册

可以将 createModal 方法挂载到 Vue 的全局属性上,方便在任何组件中调用:

import { createApp } from 'vue';
import App from './App.vue';
import createModal from './createModal';

const app = createApp(App);

// 注册为全局方法
app.config.globalProperties.$modal = createModal;

app.mount('#app');

然后在组件中使用:

this.$modal({ title: '提示', content: '这是一个全局弹窗' }).then((result) => {
  console.log(result ? '确认' : '取消');
});
(2) 插件化

将弹窗逻辑封装为一个插件,方便复用:

export default {
  install(app) {
    app.config.globalProperties.$modal = createModal;
  },
};

在主文件中引入插件:

import ModalPlugin from './plugins/modal';

app.use(ModalPlugin);

5. 总结

通过 Vue 3 的 createVNoderender 方法,我们可以轻松实现函数式弹窗。这种方式不仅灵活,还能很好地与 Composition API 结合,满足动态组件挂载的需求[[1]].

相关文章:

  • 文件管理系统
  • Spring Boot 配置属性 (Configuration Properties) 详解:优雅地管理应用配置
  • 创建多模块教程
  • ARMv8.x-M架构计算能力概览
  • react路由5和6新增及区别
  • 【论文阅读】FairCLIP - 医疗视觉语言学习中的公平性提升
  • 基于香橙派 KunpengPro学习CANN(2)——Ascend Extension for PyTorch 配置与安装
  • 深度学习框架PyTorch——从入门到精通(5)自动微分
  • Web3游戏行业报告
  • XML转义符详解:如何在XML中正确处理特殊字符
  • Vue3项目匹配PC端和移动端---两套组件
  • 生成式人工智能大模型备案政策深度解读
  • 请大家推荐一款免费的网站模版。
  • 【C++】多参数构造函数使用explict的情形
  • LSM-Tree(Log-Structured Merge-Tree)详解
  • Java 单例模式与线程安全
  • Electron使用WebAssembly实现CRC-16 MAXIM校验
  • jmeter环境搭建及使用
  • 【第9章】亿级电商平台订单系统-整体技术架构设计
  • 【华为OD-E卷 -123 判断一组不等式是否满足约束并输出最大差 100分(python、java、c++、js、c)】
  • 欧盟就逐步放松对叙利亚制裁达成一致
  • 李根读《野兽之魂》|拨开高深的布幔,直窥历史的复杂
  • 人民日报评论员观察:稳企业,全力以赴纾困解难
  • 世卫大会拒绝涉台提案,外交部:坚持一个中国原则是人心所向
  • 牛市早报|上市公司重大资产重组新规出炉,4月经济数据将公布
  • 人民日报头版:紧盯“学查改”,推动作风建设走深走实