Best Practice: How to attach components to the DOM in Vue 3
P粉362071992
2023-08-24 19:51:03
<p>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 <code><script setup></code> style component and that's another problem. </p>
<p>This seems unnecessarily difficult. </p>
<p>Here's roughly what I want to do:</p>
<ol>
<li>Get some data. Has been completed. </li>
<li>Create an instance of the Vue component: Foo.vue. </li>
<li>Pass data to it as properties. </li>
<li>Append it where I want it. </li>
</ol>
<p>The problem is, I can't use <component :is="Foo:> in the template because I don't know where it will be long after the template is rendered.</p>
<p>Are there any best practices? Is there any kind person who can provide a simple example, I would be very grateful. </p>
<p>I sometimes can't understand the Vue documentation half the time. Sorry, hate to say it, but for a newbie to Vue, they are quite obscure and make me feel stupid. </p>
<p>Here's some fake code for what I'm trying to do: </p>
<pre class="brush:php;toolbar:false;">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)
}</pre>
<p><br /></p>
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-definedVNode
with props (for example, from*.vue
imported SFC), which can be passed torender()
to render on the given container element.Destruction: Calling
render(null, container)
will destroy theVNode
attached to the container. This method should be called to clean up when the parent component is unmounted (via theunmounted
lifecycle hook).Note: This method relies on internal methods (
createVNode
andrender
), 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 an application 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 theunmounted
lifecycle hook).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