VueJs отображает все элементы при одном изменении

1

У меня есть следующая сетка образцов, в которую я вставляю некоторые новые значения в связанный список.

Нажмите в любом месте сетки, чтобы вставить новое значение в сетку.

Как вы можете видеть в скрипке, обновленная ячейка будет иметь green цвет в течение 500 мс, а все повторно отображенные элементы будут иметь yellow цвет.

Вопрос в том, как мы должны настроить компонент Vue так, чтобы он только повторно отображал измененный элемент, а не все?

Если вы посмотрите на вывод скрипта скрипта, вы увидите числа, подобные (13001, 26001,...), и это равно числу всех ячеек (1000 строк х 13 столбцов).

.yellow {
  background-color: yellow;
}

.pushed {
  background-color: lightgreen
}
<script src="https://unpkg.com/vue">
  var globalCount = 0;
</script>


<head>
  <title>Vue Render Performance</title>
</head>
<div id="demo">
  <demo-grid :data="gridData" :columns="gridColumns"> </demo-grid>
</div>

<script type="text/x-template" id="grid-template">
  <table @click="pushData()">
    <thead>
      <tr>
        <th v-for="key in columns">
          {{key}}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(entry, i) in data">
        <td v-for="(key, j) in columns" :id="'a'+i +'_'+j">
          {{renderMe(entry[key], 'a'+i +'_'+j)}}
        </td>
      </tr>
    </tbody>
  </table>
</script>


<script>
  const data = newData(1000);
  var renderedCount = 0;
  var startTime = performance.now();

  Vue.component('demo-grid', {
    props: {
      data: Array,
      columns: Array,
      renderCount: Object,
    },
    template: '#grid-template',
    methods: {
      renderMe(el, id) {

        const elm = document.getElementById(id);
        if (elm) {
          elm.className += " yellow";
        }

        if (!renderedCount) {
          renderedCount = 0
        } else {
          renderedCount++;
        }

        return el;
      },
      pushData() {
        debugger
        var push = function() {
          let cols = ["Col1", "Col2", "Col3", "Col4", "Col5", "Col6", "Col7", "Col8", "Col9", "Col10", "Col11", "Col12", "Col13"];

          var t0 = performance.now();
          for (let i = 0; i < 1; i++) {
            let newVal = Math.random() * 10000,
              row = Math.round(Math.random() * 1000),
              cellIndex = Math.floor(Math.random() * cols.length);
            cell = cols[cellIndex];
            if (data[row])
              data[row][cell] = newVal;

            var el = document.querySelector('tbody tr:nth-child(' + row + ') td:nth-child(' +
              cellIndex +
              ')');

            if (el) {
              el.className = 'pushed';

              el.scrollIntoView();

              var t = function() {
                if (el) {
                  el.className = '';
                }
                clearTimeout(t);
              };

              setTimeout(t, 500);
            }

            console.log('pushed  to cell [' + row + ',' + cellIndex + '] :' + newVal);
            console.log('Rendered Count: ' + renderedCount)
            renderedCount++;
          };
          var t1 = performance.now();
          console.log(t1 - t0)
        };

        push();
      }
    }
  });


  // bootstrap the demo
  var demo = new Vue({
    el: '#demo',
    data: {
      searchQuery: '',
      gridColumns: ["Col1", "Col2", "Col3", "Col4", "Col5", "Col6", "Col7", "Col8", "Col9", "Col10", "Col11", "Col12", "Col13"],
      gridData: data
    }
  })

  Vue.config.devtools = true;

  function newData(count) {
    const data = [];
    for (let i = 0; i < count; i++) {
      data.push({
        Col1: "Record",
        Col2: 818959475,
        Col3: 467587749,
        Col4: 438,
        Col5: 439,
        Col6: 440,
        Col7: 2.1,
        Col8: 436.2,
        Col9: 2.4,
        Col10: 5770,
        Col11: 5771,
        Col12: 5772,
        Col13: 5773
      });
    }

    return data;
  }
</script>
  • 0
    Вы не используете реактивность Vue для визуализации ваших данных.
  • 0
    @Phil, ты имеешь в виду Vue.set ?
Показать ещё 2 комментария
Теги:
performance
vue.js
vue-component
virtual-dom

1 ответ

2

Когда вы не хотите повторно отображать и весь список информации, типичным способом обработки является то, что нужно переделать в компонент. Вот обновленная версия вашего кода, которая подталкивает строки к компоненту и делает часть того, что вы делали раньше.

Vue.component("demo-row", {
  props:["entry", "columns", "rowIndex"],
    template:'
        <tr>
            <td v-for="(key, j) in columns" :id="'a'+rowIndex +'_'+j">
                {{renderMe(entry[key], 'a'+rowIndex +'_'+j)}}
            </td>
        </tr>  
  ',
  methods:{
    renderMe(el, id) {

      const elm = document.getElementById(id);
      if (elm) {
        elm.className += " yellow";
      }

      if (!renderedCount) {
        renderedCount = 0
      } else {
        renderedCount++;
      }

      return el;
    },
    }
})

Vue.component('demo-grid', {
  props: {
    items: Array,
    columns: Array
  },
  template: '#grid-template',
  methods: {
    pushData() {
      this.$parent.pushData(this.$parent.gridItems, this.$parent.gridColumns);
    }
  }
});

Пример codepen.

Заметьте, я не изменил ничего другого, что вы делаете, что, вероятно, можно было бы сделать более идиоматично в Vue, я просто хотел продемонстрировать, что нет необходимости в повторном рендеринге.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню