Почему Vue обновляет все компоненты, а не только измененный компонент в v-for? - PullRequest
1 голос
/ 12 марта 2019

У меня есть список v-for, который содержит компонент. Внутри компонента я отображаю либо <div>, либо <input> в зависимости от значения свойства. Проблема в том, что когда я изменяю значение свойства, обновляются все элементы в v-for, а не только компонент, который был изменен. Это не проблема для небольших приложений, но я заметил значительное снижение производительности при работе с большими наборами данных.

Итак, основной вопрос:

Как можно избежать рендеринга всех компонентов при обновлении только одного компонента?

Я положил все это в JSFiddle здесь . Обратите внимание, что когда вы нажимаете кнопку, чтобы показать ввод компонента 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"
  }
});

Ответы [ 3 ]

3 голосов
/ 12 марта 2019

Все ваши компоненты используют одну и ту же переменную showinput, и поэтому все они обновляются. Неважно, что вы получите только один показ, Vue не знает этого. На самом деле вы по-прежнему визуализируете интервалы, но они просто пусты.

Что вам нужно сделать, это отфильтровать данные и использовать этот фильтрованный массив в вашем v-for.

computed: {
  filteredList: function () {
     return this.list.filter( item => item.name === this.showInput )
   }
 }

А потом в вашем v-for

<div v-for=“item in filteredList” ...

LE

Если вы хотите показать всю информацию, но изменить презентацию, вы можете разделить компонент list-item на 2 компонента, один для метки и один для ввода. Затем используйте : is , чтобы выбрать, какой шаблон использовать (или даже v-if). Я создал эту скрипку , чтобы увидеть ее в действии. Обратите внимание, что onBeforeUpdate больше не будет вызываться, потому что vue воссоздает компонент.

Похоже, что в vue 3 это можно исправить, поскольку он будет поддерживать частичную визуализацию компонента.

0 голосов
/ 12 марта 2019

В вашем компоненте "list-item" у вас есть реквизит "showinput". Поэтому каждый раз, когда значение этого параметра изменяется, ваш компонент будет обновляться.

Теперь, когда вы нажимаете «Показать входные данные C», вы обновляете «showinput», и, поскольку вы используете «v-for» для компонента «list-item», «showinput» прикрепляется к каждому «list-item» и при этом все компоненты будут обновлены.

0 голосов
/ 12 марта 2019

Когда вы нажимаете кнопку «Показать C», вы обновляете переменную showInput. Теперь эта showInput переменная отправляется в качестве реквизита каждому <list-item /> в вашем v-for, и таким образом вы обновляете все компоненты.

...