如何创建 Vue 组件的新实例,并使用方法最终销毁它们?



我正在尝试根据用户输入将组件动态添加到 DOM。我实际上遇到了 ±200 个按钮/触发器的情况,单击时需要创建/显示childComponent实例(这是一种信息窗口/模态(。

然后,我还需要在以后用户"关闭"组件时能够删除/隐藏它们。

我在想象这样的事情?

<template>
<div ref="container">
<button @click="createComponent(1)" />
...
<button @click="createComponent(n)" />

<childComponent ref="cc53" :num="53" v-on:kill="destroyComponent" />
...
<childComponent ref="ccn" :num="n" v-on:kill="destroyComponent"/>
</div>
</template>
<script>
import childComponent from '@/components/ChildComponent'
export default {
components: {childComponent},
methods: {
createComponent (num) {
// How do I create an instance of childComponent with prop 'num' and add it to this.$refs.container?
},
destroyComponent (vRef) {
// How do I destroy an instance of childComponent?
this.vRef.$destroy();
}
}
}
</script>

所需的可能childComponent实例的数量是有限的、不可变的,并且在渲染之前是已知的,所以我可以循环和v-show它们,但您的典型用户可能只需要查看几个,当然也只需要同时查看几个。

我的问题:

首先,鉴于其中有 ±200 个,仅在需要时动态创建实例是否有任何性能优势,而不是v-for循环childComponents,让 Vue 管理 DOM?

其次,即使对于这种特殊情况v-for要走的路,如果可能的子组件总数未知或动态,如何处理?这是渲染函数和JSX的工作吗?

如果我理解,您想显示将:num作为道具的相同组件的列表。

首先,你必须记住 Vue 是一个"数据驱动的应用程序",这意味着你需要将你的列表表示为arrayobject中的数据,在这种情况下,你可以使用myList数组和v-for循环在模板中显示你的子组件列表。

添加和删除操作必须在它自己的myList数组上进行,一旦完成,它将自动应用于您的模板。

  • 添加新实例,只需使用myList.push(n)
  • 要删除实例,请使用myLsit.splice(myLsit.indexOf(n), 1);

结果应如下所示:

<template>
<input v-model="inputId" />
<button @click="addItem(inputId)">Add Item</button>
<childComponent
v-for="itemId in myList" 
:key="itemId" 
:ref="'cc' + itemId" 
:num="itemId"
@kill="removeItem(itemId)"
/>
</template>
<script>
data(){
return{
inputId : 0,
myList : []
}
},
methods:{
addItem(id){
this.myList.push(id)
},
removeItem(id){
this.myLsit.splice(this.myLsit.indexOf(id), 1)
}
}
</script>

附言 :

  • 没有测试代码,如果有任何错误,请告诉我
  • @kill方法必须由childComponent发出,$emit('kill', this.num)
  • 这是一个很好的教程,可以更好地了解v-for

性能惩罚

由于 ±200 个元素的可能性有限,我非常怀疑它会导致任何性能问题,并且为了进一步微调,您可以使用v-if而不是使用v-show它会减少总内存占用,但如果您要不断更改项目,则会增加渲染时间。

其他方法

如果x元素的可能性没有限制,那么它仍然v-for包含v-if指令的项目。

但是如果用户只能同时看到一个项目(或多个但有限的项目(,而不是v-for,则最好直接将属性绑定到childComponent

例如,如果子组件是当用户单击表行的编辑按钮时应用程序将显示的模式。我们可以拥有一个模态并将表单属性绑定到它,而不是拥有x数量的模态,每个模态都有一行的可编辑内容并显示与编辑按钮相关的模态。这种方法通常通过拥有像vuex这样的状态管理库来实现。

最后,这是一个基于vuex的实现,可以使用,如果用户只能同时看到一个childComponent,它可以很容易地扩展以支持同时查看多个childComponent

商店.js

export Store {
state: {
childComponentVisible: false,
childComponentNumber: 0
},
mutations: {
setChildComponentNumber(state, value) {
if(typeof value !== 'number')
return false;
state.childComponentNumber = value;
},
setChildComponentVisibility(state, value) {
if(typeof value !== 'boolean')
return false;
state.childComponentVisible = value;
}
}
}

child-component.vue

<template>
<p>
{{ componentNumber }}
<span @click="close()">Close</span>
</p>
</template>
<script>
export default {
methods: {
close() {
this.$store.commit('setChildComponentVisibility', false);
}
}
computed: {
componentNumber() {
return this.$store.state.childComponentNumber;
}
}
}
</script>

list-component.vue

<template>
<div class="list-component">
<button v-for="n in [1,2,3,4,5]" @click="triggerChildComponent(n)">
{{ n }}
</button>
<childComponent v-if="childComponentVisible"/>
</div>
</template>
<script>
export default {
methods: {
triggerChildComponent(n) {
this.$store.commit('setChildComponentNumber', n);
this.$store.commit('setChildComponentVisibility', true);
}
},
computed: {
childComponentVisible() {
return this.$store.state.childComponentVisible;
}
}
}
</script>

注意:上面编写的代码只是抽象的,未经测试,您可能需要对其进行一些更改以使其适用于您自己的情况。

有关vuex的更多信息,请在此处查看其文档。

最新更新