Vue3 模态类(Model)封装方案 - 初探

4,608 阅读3分钟

如果你想节省时间,建议阅读该篇文章:

以最简单的方式封装 Vue3 模态(Modal) 类组件

这篇文章是对三篇文章的总结与经验,探索出的最佳实现方法。

如果你想进一步的了解 Modal 的实现机理,那么请往下阅读


Vue3 模态类(Model)封装方案 - 初探

Vue3 模态类(Model)封装方案 - 实践

Vue3 模态类(Model)封装方案 - 定制

想必大家使用 Vue 开发时,都有使用过 Element 或 Ant Design of Vue 的模态框

例如 Ant Design of Vue 中的 a-message:

  <a-modal v-model="visible" title="Title" on-ok="handleOk">
    自定义内容
  </a-modal>

又或者直接在 js 代码中直接调起的 ElMessageBox:

import { ElMessageBox } from 'element-plus';

ElMessageBox.confirm('此操作将永久删除该文件, 是否继续?', '提示')
    .then(()=> {
    })
    .catch(()=> {
    })

例如在项目当中,有需要定义模态框调用的场景,就需要掌握自定义模态框的封装

就好比如在一个后台管理系统中的一个图片选择器

ImageSelect({ multiple: true })
    .then((images)=> {
    
    })

又或者是使用组件库的模态框自定义样式功能,导致需要写全局类名覆盖组件模态框,复用率低下

  <!-- 组件 A -->
  <el-dialog custom-class="purchase-dialog">
    ...自定义内容...
  </el-dialog>
  <!-- 组件 B -->
  <el-dialog custom-class="purchase-dialog">
    ...自定义内容...
  </el-dialog>

可见要封装好一个模态框组件的重要性还是很高的,那么整个大纲中会循环渐进的告诉你如果需要自定义封装一个又支持在 template 中使用,又支持在 js 代码中直接调用的对话框,以及如何利用组件库已有的模态框在不影响其复用性,扩展性的前提下进行二次封装。

本篇文章主要讲解要封装模态框之前要有所了解的一些技巧和 API

  • 虚拟节点创建 (create vnode)
  • 虚拟节点渲染 (render vnode)
  • Vue3 新增瞬移组件 (teleport)

虚拟节点创建 (create vnode)

虚拟节点可以理解成节点描述对象,它描述了应该怎样去创建真实的DOM节点。

利用 Vue3 默认导出的 h 函数,创建 vnode ,h 函数可以有多种传参方式:

import { h } from 'vue'
// 传入组件内容, 与组件 props 参数, 生成虚拟节点
const vnode = h(Component, props)

// 组件内容可为导入组件, 例如
import Component from './Component.vue'
const vnode = h(Component, props)
// 也可为 template 例如
const vnode = h('<div>hello world!!</div>', props)
// 也可为节点的描述数据 例如
const vnode = h('div', { id: 'app' }, [h('span', '我是 span')])

虚拟节点渲染 (render vnode)

利用 Vue3 默认导出的 render 函数,渲染至 document.body 当中:

import { h, render } from 'vue'
render(h('div', '我是一个 div'), container)

利用一个中间节点容器,卸载节点下所有 vnode:

import { h, render } from 'vue'
const container = document.createElement('div')
render(h('div', '我是一个 div'), container)
document.body.appendChild(container.firstElementChild)
// 销毁真实节点的所有实例 ( 卸载组件 )
// 这里不需要调用 document.body.removeChild(container.firstElementChild)
// 因为调用 render(null, container) 为我们完成了这项工作
render(null, container)

下一篇:Vue3 模态类(Model)封装方案 - 实践