vue通过函数渲染组件

Vue 2024-08-02 265

原理: 通过vue提供的render, createVNode方法将vue组件转为dom挂载到指定的元素下

import MaterialFolderDialog from "./MaterialFolderDialog.vue"
import { render, createVNode, nextTick } from "vue"

export function open(data: any) {
  let vNode = null
  const container = document.createElement("div")
  // 移除组件
  const doClose = () => {
    console.log("close...")
    vNode = null
    render(null, container)
    container.remove()
  }
  // createVNode 支持以下6个参数
  // type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT
  // props?: (Data & VNodeProps) | null 子组件接收的值
  // children?: unknown,
  // patchFlag?: number,
  // dynamicProps?: string[] | null,
  // isBlockNode?: boolean
  // type: 表示要创建的节点的类型。可以是:
  // 一个字符串,表示一个 HTML 标签(例如 'div')。
  // 一个组件对象,表示一个 Vue 组件。
  // 一个异步组件的工厂函数。
  // props: (可选)表示要传递给该节点的属性和事件监听器。这是一个对象。
  // children: (可选)表示子节点。可以是一个字符串(表示文本节点),一个数组(表示多个子节点),或者一个对象(表示具名插槽)。
  vNode = createVNode(MaterialFolderDialog, { ...data, doClose })
  nextTick(() => {
    render(vNode, container) // 将组件的vNode挂载到container节点下
    console.log(container) // dom
    document.body.appendChild(container) // 挂载到body
  })
}

MaterialFolderDialog组件

<template>
  <el-dialog v-model="visible" title="新建文件夹" width="600px" @opened="open" @close="close">{{ text }} </el-dialog>
</template>
<script setup lang="ts">
import { ref } from "vue"
import { ElDialog } from "element-plus"

const props = defineProps({
  text: {
    type: String,
    default: "测试",
  },
  doClose: {
    type: Function,
    default: () => null,
  },
})
const visible = ref(true)
const open = () => {
  console.log(props.text)
}
const close = () => {
  props.doClose()
}
</script>
<style scoped lang="scss"></style>

标签:Vue

文章评论

评论列表

已有0条评论