选项 1:createVNode(component, props) 和 render(vnode, container)
创建: 使用 createVNode() 来创建带有 props 的组件定义的 VNode(例如,从 *.vue 导入的 SFC),可以将其传递给 render() 以进行渲染在给定的容器元素上。
销毁:调用附加到容器的render(null, container) destroys the VNode。当父组件卸载(通过unmounted lifecycle hook)时,这应该被称为清理。
// renderComponent.js
import { createVNode, render } from 'vue'
export default function renderComponent({ el, component, props, appContext }) {
let vnode = createVNode(component, props)
vnode.appContext = { ...appContext }
render(vnode, el)
return () => {
// destroy vnode
render(null, el)
vnode = undefined
}
}
警告:这种方法依赖于内部方法(createVNode 和 render),可以在未来的版本中重构或删除。
demo 1
选项 2:createApp(component, props) 和 app.mount(container)
创建:使用createApp(),它返回一个application instance。该实例有mount(),可用于在给定容器elemenet上渲染组件。
销毁:应用实例有unmount()来销毁应用和组件实例。当父组件卸载(通过unmounted lifecycle hook)时,这应该被称为清理。
// renderComponent.js
import { createApp } from 'vue'
export default function renderComponent({ el, component, props, appContext }) {
let app = createApp(component, props)
Object.assign(app._context, appContext) // must use Object.assign on _context
app.mount(el)
return () => {
// destroy app/component
app?.unmount()
app = undefined
}
}
警告:这种方法为每个组件创建一个应用程序实例,如果需要在文档中同时实例化多个组件,这可能是不小的开销。
demo 2
示例用法
<script setup>
import { ref, onUnmounted, getCurrentInstance } from 'vue'
import renderComponent from './renderComponent'
const { appContext } = getCurrentInstance()
const container = ref()
let counter = 1
let destroyComp = null
onUnmounted(() => destroyComp?.())
const insert = async () => {
destroyComp?.()
destroyComp = renderComponent({
el: container.value,
component: (await import('@/components/HelloWorld.vue')).default
props: {
key: counter,
msg: 'Message ' + counter++,
},
appContext,
})
}
</script>
<template>
<button @click="insert">Insert component</button>
<div ref="container"></div>
</template>