为什么 Vue 更新所有组件而不是只更新 v-for 中更改的组件?

Why is Vue updating the all components instead of just the changed component in a v-for?

我有一个 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"
  }
});

当您按下 "Show C" 按钮时,您正在更新 showInput 变量。现在这个 showInput 变量作为 prop 发送给你的 v-for 中的每个 <list-item /> 并且通过这样做,你正在更新所有组件。

您的所有组件都使用相同的变量 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 to choose what template to use (or even a v-if). I created this fiddle 来查看它的实际效果。请注意,onBeforeUpdate 不会再被调用,因为 vue 会重新创建组件。

这似乎在 vue 3 中可以修复,因为它将支持组件的部分渲染。

在您的组件 "list-item" 中,您有一个名为 "showinput" 的道具。 因此,每次更改此道具值时,您的组件都会更新。

现在,无论何时单击 "Show C input",都会更新 "showinput",并且当您将 "v-for" 用于 "list-item" 组件时,每个组件都附有 "showinput" "list-item" 因此所有组件都将更新。