Vue 3 doesn't have Vue.extend() method, so example here doesn't work: https://css-tricks.com/creating-vue-js-component-instances-programmatically/
I have tried this solution: https://jsfiddle.net/jamesbrndwgn/fsoe7cuy/
But it causes warning in console:
Vue received a Component which was made a reactive object. This can lead to unnecessary performance overhead, and should be avoided by marking the component with markRaw
or using shallowRef
instead of ref
.
enter image description here
So, what is the proper way to add components dynamically (programmatically) in Vue 3?
UploadTaskTagManager.vue
<template>
<button @click="addTag()" type="button">Add new tag</button>
<br>
<div>
<div v-for="child in children" :key="child.name">
<component :is="child"></component>
</div>
</div>
</template>
<script>
import UploadTaskTag from "./UploadTaskTag";
export default {
name: "UploadTaskTagManager",
components: {UploadTaskTag},
data() {
return {
children: []
}
},
methods: {
addTag() {
this.children.push(UploadTaskTag);
},
}
}
</script>
UploadTaskTag.vue
<template>
<div>
<select @change="onChangeTag($event)" v-model="currentTag">
<option v-for="tag in getAllTags()" :key="tag.tag_name" :value="tag">{{tag.tag_name}}</option>
</select>
<input maxlength="16" class="tag-input" ref="inputField"/>
<button @click="removeTag($event)" type="button">-</button>
<br>
</div>
</template>
<script>
export default {
name: "UploadTaskTag",
data() {
return {
tags: [],
currentTag: {}
}
},
methods: {
onChangeTag(event) {
this.$refs.inputField.value = this.currentTag.tag_name;
},
getAllTags() {
return this.$store.state.allTags;
},
removeTag() {
this.$el.parentElement.removeChild(this.$el)
},
getValue(fieldIndex) {
let tag = this.tags[fieldIndex];
return tag ? tag.tag_name : "";
},
}
}
</script>
To use a component in another component, follow the below steps: Import the . vue file into the component script tag. Add the default export to the component property.
Open the file in your code editor. Create the component's template section by adding <template></template> to the top of the file. Create a <script></script> section below your template section. Inside the <script> tags, add a default exported object export default {} , which is your component object.
Find answer to this question in the following article and discover the benefits of Composition API. Vue 3 introduced a new approach to creating components called Composition API . It is an alternative to the Options API . The Composition API is fully optional and you don't need to use it if you want to use Vue 3.
just use createApp
instead of Vue.extend
here's a example of simple vue3 components programmatically
import Button from 'Button.vue'
import { createApp } from "vue"
// Creating the Instance
// use createApp https://v3.vuejs.org/api/global-api.html#createapp
var ComponentApp = createApp(Button)
import Button from "./Button.vue"
// inserting to dom
const wrapper = document.createElement("div")
ComponentApp.mount(wrapper)
document.body.appendChild(wrapper)
set props or slot is a little different by use h
, https://v3.vuejs.org/api/global-api.html#h
import Button from 'Button.vue'
import { createApp, h } from "vue"
var ComponentApp = createApp({
setup () {
return () => h(Button, {type: "primary"}, "default slot as children")
}
})
If I understood you correctly, then the solution will be like this
You can learn more about 'defineAsyncComponent' on the official website https://v3.vuejs.org/api/global-api.html#defineasynccomponent
<template>
<button @click="addTag()" type="button">Add new tag</button>
<br>
<div>
<div v-for="child in children" :key="child.name">
<component :is="child"></component>
</div>
</div>
</template>
<script>
import { defineAsyncComponent, defineComponent, ref } from "vue"
export default defineComponent({
components: {
UploadTaskTag: defineAsyncComponent(() => import("./UploadTaskTag"))
},
setup() {
const children = ref([])
const addTag = () => {
children.value.push('UploadTaskTag')
console.log(children.value)
}
return {
addTag,
children
}
},
})
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With