Запрос относительно реактивности массива в Vue.js 2

Я написал компонент сетки, который поддерживает дочерние строки, то есть переключаемую строку с ячейкой который занимает всю ширину таблицы под каждой нормальной строкой. Чтобы отслеживать состояние дочерних строк, я использую свойство данных с именем openChildRows, которое по умолчанию равно пустому массиву. Когда пользователь щелкает значок переключателя, который присутствует в первом столбце каждой строки, открывается дочерняя строка этой строки. Дополнительный щелчок закрывает его. Массив openChildRows содержит идентификаторы открытых строк.

Проблема, с которой я сталкиваюсь, заключается в том, что когда я использую компонент для дочерней строки, все открытые строки, которые появляются после, будут повторно подключены. Это явно неэффективно, особенно если компонент дочерней строки отправляет запрос ajax при монтировании. В идеале я бы хотел, чтобы монтировалась только новая дочерняя строка.

Я написал сетку, используя JSX для шаблонов. Ниже приведен соответствующий код:

Шаблон строк:

module.exports = function(h, that) {
    var rows = [];
    var columns;
    var rowKey = that.opts.uniqueKey;

    var rowClass;
    var data = that.source=='client'?that.filteredData:that.tableData;
    var recordCount = (that.Page-1) * that.limit;

    data.map(function(row, index) {

      index = recordCount + index + 1;

      columns = [];

      if (that.hasChildRow) {
        var childRowToggler = <td><span on-click={that.toggleChildRow.bind(that,row[rowKey])} class={`VueTables__child-row-toggler ` + that.childRowTogglerClass(row[rowKey])}></span></td>;
        if (that.opts.childRowTogglerFirst) columns.push(childRowToggler);
      }


      that.allColumns.map(function(column) {
          let rowTemplate = that.$scopedSlots && that.$scopedSlots[column];

          columns.push(<td class={that.columnClass(column)}>
            {rowTemplate ? rowTemplate({ row, column, index }) : that.render(row, column, index, h)}
        </td>)
      }.bind(that));

      if (that.hasChildRow && !that.opts.childRowTogglerFirst) columns.push(childRowToggler);

      rowClass = that.opts.rowClassCallback?that.opts.rowClassCallback(row):'';

      rows.push(<tr class={rowClass} on-click={that.rowWasClicked.bind(that, row)} on-dblclick={that.rowWasClicked.bind(that, row)}>{columns} </tr>);

    // Below is the code that renders open child rows
      if (that.hasChildRow && this.openChildRows.includes(row[rowKey])) {

        let template = this._getChildRowTemplate(h, row);

        rows.push(<tr class='VueTables__child-row'><td colspan={that.allColumns.length+1}>{template}</td></tr>);
      }

    }.bind(that))

    return rows;

}

Код метода переключения:

  module.exports = function (rowId, e) {

  if (e) e.stopPropagation();

  if (this.openChildRows.includes(rowId)) {
    var index = this.openChildRows.indexOf(rowId);
    this.openChildRows.splice(index,1);
  } else {
    this.openChildRows.push(rowId);
  }
};

Метод _getChildRowTemplate:

module.exports = function (h, row) {
  // scoped slot
  if (this.$scopedSlots.child_row) return this.$scopedSlots.child_row({ row: row });

  var childRow = this.opts.childRow;

  // render function
  if (typeof childRow === 'function') return childRow.apply(this, [h, row]);

  // component
  return h(childRow, {
    attrs: {
      data: row
    }
  });
};

person Matanya    schedule 23.11.2017    source источник


Ответы (1)


Я изменил:

if (that.hasChildRow && this.openChildRows.includes(row[rowKey])) {

        let template = this._getChildRowTemplate(h, row);

        rows.push(<tr class='VueTables__child-row'><td colspan={that.allColumns.length+1}>{template}</td></tr>);
}

to:

  rows.push(that.hasChildRow && this.openChildRows.includes(row[rowKey])?
    <tr class='VueTables__child-row'><td colspan={that.allColumns.length+1}>{this._getChildRowTemplate(h, row)}</td></tr>:h());

И вуаля!

person Matanya    schedule 24.11.2017