为啥 Vue 更新所有组件,而不仅仅是 v-for 中更改的组件?
Posted
技术标签:
【中文标题】为啥 Vue 更新所有组件,而不仅仅是 v-for 中更改的组件?【英文标题】:Why is Vue updating the all components instead of just the changed component in a v-for?为什么 Vue 更新所有组件,而不仅仅是 v-for 中更改的组件? 【发布时间】:2019-08-03 03:06:27 【问题描述】:我有一个 v-for
列表,其中包含一个组件。在组件内部,我根据属性的值显示<div>
或<input>
。问题是当我更改属性值时,v-for 中的所有项目都会更新,而不仅仅是更改的组件。这不是小型应用程序的问题,但我注意到在处理较大的数据集时性能显着下降。
所以基本问题是:
当只更新一个组件时,如何避免渲染所有组件?
我把它全部放在JSFiddle here 中。请注意,当您单击按钮以显示 C 组件输入时,所有组件都会重新呈现(显示在控制台中),而不仅仅是 C 组件。
HTML
<div id="app">
<button @click="showinput = 'C'">
Show C input
</button>
<br>
<br>
<div v-for="item in list" :key="item.id">
<list-item :item=item :showinput="showinput"></list-item>
</div>
</div>
<template id="list-item"> <span> <div v-if="showinput !== item.name">
item.name</div>
<input v-else
type="text"
v-model.lazy="item.name" >
</span>
</template>
JS
Vue.component('list-item',
template: '#list-item',
props: ['item', 'showinput'],
data ()
return
,
beforeUpdate()
console.log("Updating " + this.item.name)
);
// create a new Vue instance and mount it to our div element above with the id of app
var vm = new Vue(
el: '#app',
data:
list: [name: "A", id: 1, name: "B", id: 2, name: "C", id: 3,],
showinput: "X"
);
【问题讨论】:
【参考方案1】:当您按下“显示 C”按钮时,您正在更新 showInput
变量。现在这个showInput
变量作为prop 发送到v-for
中的每个<list-item />
,通过这样做,您正在更新所有组件。
【讨论】:
【参考方案2】:您的所有组件都使用相同的变量 showinput,因此所有组件都已更新。最终只显示一个并不重要,vue 不知道这一点。实际上,您仍在渲染跨度,但它们只是空的。
您应该做的是过滤数据并在您的 v-for 中使用过滤后的数组。
computed:
filteredList: function ()
return this.list.filter( item => item.name === this.showInput )
然后在你的 v-for 中
<div v-for=“item in filteredList” ...
乐
如果您想显示所有信息,但要更改显示方式,您可以将list-item
组件拆分为 2 个组件,一个用于标签,一个用于输入。然后使用:is 选择要使用的模板(甚至是v-if
)。我创建了这个fiddle 来查看它的实际效果。请注意,onBeforeUpdate
将不再被调用,因为 vue 会重新创建组件。
在 vue 3 中这似乎可以修复,因为它将支持组件的部分渲染。
【讨论】:
谢谢!我明白这个问题。但是,计算过滤器真的可行吗?这会过滤掉一些数据:我希望显示所有数据 - 只是以不同的形式。解决方案是否可以让一个子组件带有输入字段,一个没有,然后在父组件中执行 v-if 来决定显示哪个? 您可以使用补充过滤器,它使用 !==,而不是 ===。但这是一个不同的问题,您可能应该就 SO 提出其他问题。 谢谢,但我不关注这个。我想以相同的顺序显示所有数据 - 只有一些作为输入字段,一些作为跨度。那么我怎样才能使用计算过滤器呢?请您指出我应该搜索的正确方向吗?同时,我确实尝试了我自己的建议,使用两个不同的子组件和 v-if,虽然性能稍微好一点,但并没有太大的区别。 感谢您的帮助!【参考方案3】:在您的组件“list-item”中,您有一个名为“showinput”的道具。 所以每次改变这个 prop 的值,你的组件都会更新。
现在,每当您单击“显示 C 输入”时,您都会更新“showinput”,并且当您将“v-for”用于“list-item”组件时,每个“list-item”都会附加“showinput”并且因此所有组件都会更新。
【讨论】:
以上是关于为啥 Vue 更新所有组件,而不仅仅是 v-for 中更改的组件?的主要内容,如果未能解决你的问题,请参考以下文章
Vue 不会使用动态组件从 Vuex 更新 v-for 中的项目