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