Gen*_*ich 12 javascript vue.js vuejs3
我想在 SFC 中的 Vue 3 应用程序中动态创建一个组件,并将其附加到 DOM。我正在使用<script setup>
样式组件,这是另一个问题。
这似乎不必要地困难。
这或多或少是我想做的:
问题是我无法在模板中执行 <component :is="Foo:> 因为我不知道它会在哪里,直到模板渲染后很长时间。
这有最佳实践吗?某个善良的灵魂可以提供一个简单的例子,我们将不胜感激。
我有一半时间无法从 Vue 文档中弄清楚。抱歉,我不想这么说,但它们对于 Vue 新手来说相当不透明,让我觉得很愚蠢。
这是一些假装代码,说明了我想要做什么
import Foo from "../components/Foo.vue"
function makeAFoo(p, data){
// instantiate my Foo.vue (not sure how to do this inline), and pass it the data it needs
let foo = new Foo(data); // if only it were this simple, right?
// Append it to p (which is an HTML Element)
p.appendChild(foo)
}
Run Code Online (Sandbox Code Playgroud)
ton*_*y19 27
createVNode(component, props)
和render(vnode, container)
创建:用于使用propscreateVNode()
创建VNode
组件定义(例如,从 导入的 SFC ),可以将其传递到给定容器元素上进行渲染。*.vue
render()
销毁:调用render(null, container)
会销毁VNode
附加到容器的内容。unmounted
当父组件卸载时(通过生命周期钩子) ,这应该被称为清理。
// 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
}
}
Run Code Online (Sandbox Code Playgroud)
警告:此方法依赖于内部方法 (createVNode
和render
),这些方法可能会在未来版本中重构或删除。
createApp(component, props)
和app.mount(container)
创建:使用createApp()
,返回一个应用程序实例。该实例具有mount()
,可用于在给定容器元素上呈现组件。
销毁:应用程序实例必须unmount()
销毁应用程序和组件实例。unmounted
当父组件卸载时(通过生命周期钩子) ,这应该被称为清理。
// 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
}
}
Run Code Online (Sandbox Code Playgroud)
警告:此方法为每个组件创建一个应用程序实例,如果需要在文档中同时实例化许多组件,这可能是不小的开销。
<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>
Run Code Online (Sandbox Code Playgroud)