1

我有一个v-for包含一个组件的列表。在组件内部,我根据属性的值显示 a<div>或 a 。<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"
  }
});
4

3 回答 3

3

您的所有组件都使用相同的变量 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)。我创建了这个小提琴来看看它的实际效果。请注意,onBeforeUpdate不会再调用它,因为 vue 会重新创建组件。

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

于 2019-03-12T15:29:56.530 回答
0

当您按下“显示 C”按钮时,您正在更新showInput变量。现在这个showInput变量作为一个道具发送到<list-item />你的每个人v-for,通过这样做,你正在更新所有组件。

于 2019-03-12T15:23:05.703 回答
0

在您的组件“列表项”中,您有一个名为“showinput”的道具。所以每次,这个 prop 值改变,你的组件都会更新。

现在,每当您单击“显示 C 输入”时,您正在更新“showinput”,并且当您使用“v-for”作为“list-item”组件时,“showinput”附加到每个“list-item”,因此所有组件将会被更新。

于 2019-03-12T15:32:05.457 回答