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.

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>