I want to dynamically create a component in my Vue 3 application, inside a Single File Component (SFC), and append it to the DOM. I'm using a style component and that's another problem.
This seems unnecessarily difficult.
Here's roughly what I want to do:
- Get some data. Has been completed.
- Create an instance of the Vue component: Foo.vue.
- Pass data to it as properties.
- Append it where I want it.
The problem is, I can't use 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 required data let foo = new Foo(data); // If only it were that simple, right? //Append it to p (which is an HTML element) p.appendChild(foo) }
An easier way is to use v-if or v-for.
Instead of dealing with the component directly, it is better to deal with the state of the component and let Vue's responsive magic work
This is an example, dynamically add a component (Toast), just operate the state of the component
Toast.vue file: The v-for here is reactive, whenever a new error is added to the errors object, it will be rendered
ErrorTrigger.vue: Whenever a click event occurs, we push an error to the errors object
Full example:https://stackblitz.com/edit/vitejs-vite-mcjgkl
Option 1: Use
createVNode(component, props)andrender(vnode, container)Create:Use
createVNode()to create a component-definedVNodewith props (for example, from*.vueimported SFC), which can be passed torender()to render on the given container element.Destruction:Calling
render(null, container)will destroy theVNodeattached to the container. This method should be called to clean up when the parent component is unmounted (via theunmountedlifecycle 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 } }Note:This method relies on internal methods (
createVNodeandrender), which may be refactored or removed in future versions.Demo 1
Option 2: Use
createApp(component, props)andapp.mount(container)Create:Use
createApp()to create anapplication instance. This instance has amount()method that can be used to render the component on a given container element.Destruction:Application instances have
unmount()methods to destroy application and component instances. This method should be called to clean up when the parent component is unmounted (via theunmountedlifecycle 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) // 必须使用Object.assign在_context上 app.mount(el) return () => { // 销毁app/component app?.unmount() app = undefined } }Note:This method creates an application instance for each component. If multiple components need to be instantiated in the document at the same time, it may cause considerable overhead.
Demo 2
Example usage