如何以编程方式添加 Vue 3 组件?
Posted
技术标签:
【中文标题】如何以编程方式添加 Vue 3 组件?【英文标题】:How to add Vue 3 components programmatically? 【发布时间】:2021-05-16 02:36:31 【问题描述】:Vue 3 没有 Vue.extend() 方法,所以这里的例子不起作用: https://css-tricks.com/creating-vue-js-component-instances-programmatically/
我已经尝试过这个解决方案: https://jsfiddle.net/jamesbrndwgn/fsoe7cuy/
但它会在控制台中引起警告:
Vue 收到了一个组件,该组件被制成反应性对象。这可能会导致不必要的性能开销,应通过使用markRaw
标记组件或使用shallowRef
而不是ref
来避免。
enter image description here
那么,在 Vue 3 中动态(以编程方式)添加组件的正确方法是什么?
上传任务标签管理器.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>
【问题讨论】:
【参考方案1】:只需使用createApp
而不是Vue.extend
这是一个以编程方式的简单 vue3 组件示例
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)
使用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")
)
【讨论】:
不知何故,使用 createApp() 以编程方式添加一个小的 Vue 组件感觉不对。它让我想起了臃肿和头顶的景象。不过我必须把它交给你,你的回答就可以了。 我面临着类似的问题。我只想动态创建一个组件并将其附加到 Vue 3 中的 DOM 中,这似乎不必要地困难。为什么要创建一个新的 Vue 实例?我不明白。没有更简单的方法吗?【参考方案2】:如果我理解正确,那么解决方案将是这样的
您可以在官网https://v3.vuejs.org/api/global-api.html#defineasynccomponent了解更多关于'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>
【讨论】:
以上是关于如何以编程方式添加 Vue 3 组件?的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式更改 Vuetify 选项卡和 vue-router