Выполните операцию над строкой таблицы данных в дочернем компоненте Vue после загрузки асинхронных данных. - PullRequest
0 голосов
/ 24 октября 2019

У меня есть дочерний компонент, который использует Vuetify v-data-table , и когда отображается страница, на которой отображается этот компонент и его родительский элемент, я хочу выделить первый элемент в списке (данные для элемента также отображаются над ним в родительском компоненте). Я также хочу, чтобы строка была выделена, когда она выбрана, и данные для этой строки отображаются в родительском элементе.

На основании этого ответа у меня вторая часть работает нормально, ипервая часть (выделение первой строки при начальном отображении) работает, но только в некоторой степени.

<template>
  <div>
    <v-data-table
      :headers="headers"
      :items="items"
      :search="search"
      :key="tableKey"
      :pagination.sync="pagination"
      disable-initial-sort
      rowKey
    >
    <template slot="items" slot-scope="props">
      <tr @click="clicked(props.item)" :class="{'secondary': props.item[rowKey]===selectedCode}">
        <td v-for="header in headers" :key="header.value">
          <BaseTableColumn
            :item="props.item"
            :index="header.value"
            :format="header.format"
          />
        </td>
      </tr>
    </template>
  </v-data-table>
  </div>
</template>

<script>
export default {
  name: 'BaseTable',
  props: {
    headers: Array,
    items: Array,
    search: String,
    tableKey: String,
    rowKey: String,
  },
  data: () => ({
    pagination: {
      rowsPerPage: 10,
      totalItems: -1,
    },
    selectedCode: -1,
    itemsYN: false,
  }),
  components: {
    BaseTableColumn: () => import('@/components/base/BaseTableColumn'),
  },
  methods: {
    clicked(row) {
      window.scrollTo(0, 0);
      this.selectedCode = row[this.rowKey];
      this.$set(row, 'selected', true);
      this.$emit('rowClick', row);
    },
  },
  mounted() {
    // Select the first item in the list of items (if there are any)
    // and highlight it.
    if (this.items.length > 0) {
      this.selectedCode = this.items[0][this.rowKey];
      this.$set(this.items[0], 'selected', true);
    }
  },
};
</script>

, где этот компонент вызывается из родительского элемента следующим образом:

<BaseTable
  :headers="headers"
  :items="alerts"
  :search="search"
  rowKey="messageId"
  @rowClick="rowClick"
/>

Asсейчас у меня есть код для начального выделения в хуке mounted(). Это прекрасно работает, когда все данные items уже доступны во время монтирования, но если вызов для получения данных занимает больше времени и не загружается до тех пор, пока он не достигнет этой точки в жизненном цикле, тогда я не получу выделение,То же самое верно, если я использовал created() hook

Моя мысль состояла в том, чтобы посмотреть реквизит items, и как только он заполнится, вызовите код выделения, например, так:

  watch: {
    items(val) {
      if (this.items.length > 0) {
        this.highlightFirst(val)
      }
    },
  },
  methods: {
    clicked(row) {
      window.scrollTo(0, 0);
      this.selectedCode = row[this.rowKey];
      this.$set(row, 'selected', true);
      this.$emit('rowClick', row);
    },
    highlightFirst(items) {
      this.selectedCode = this.items[0][this.rowKey];
      this.$set(this.items[0], 'selected', true);
    },
  },
  mounted() {
    // Select the first item in the list of items (if there are any)
    // and highlight it.
    if (this.items.length > 0) {
      this.highlightFirst(this.items);
    }
  },

, но, поскольку items обновляется всякий раз, когда выбирается строка, это переопределяет метод clicked(), поэтому первый элемент выделяется, а не тот, по которому щелкнули.

Поскольку этот компонент является дочерним по отношению к 14 компонентам, я бы хотел обработать это в этом компоненте, вместо того, чтобы добавить пропущенную вину от всех родителей, чтобы указать, когда данные загружаются. Как выделить первую строку при начальной загрузке страницы, ожидая передачи асинхронных данных, не нажимая на метод clicked() при нажатии на отдельную строку?

Ответы [ 2 ]

0 голосов
/ 25 октября 2019

Мне удалось исправить это проще с помощью следующего кода:

  props: {
    headers: Array,
    items: Array,
    search: String,
    tableKey: String,
    rowKey: String,
  },
  data: () => ({
    ...
    selectedCode: -1,
  }),  
  methods: {
    clicked(row) {
      window.scrollTo(0, 0);
      this.selectedCode = row[this.rowKey];
      this.$set(row, 'selected', true);
      this.$emit('rowClick', row);
    },
    highlightFirst(items) {
      this.selectedCode = this.items[0][this.rowKey];
      this.$set(this.items[0], 'selected', true);
    },
  },
  updated() {
    if (this.selectedCode === -1 && && (typeof this.items === 'object') && this.items.length > 0) {
      this.highlightFirst(this.items);
    }
  },

Как только this.selectedCode имеет значение после запуска highlightFirst(), ничего не происходит в update(), а clicked() метод работает, как и должно быть при щелчке строки.

0 голосов
/ 24 октября 2019

Вы можете объявить переменную, в которой можно сохранить true при click кнопке и установить false при вводе watch

data: (){
      return {
          fromClick: true;
      }
  },
  watch: {
    items(val) {
      if (!fromClick) {
        this.highlightFirst();
      }
      this.fromClick = false;
    }
  },
  methods: {
    clicked(row) {
      this.fromClick = true;
      window.scrollTo(0, 0);
      this.hightlightRow(row);
      this.$emit('rowClick', row);
    },
    highlightFirst() {
      if (this.items.length > 0) {
        this.hightlightRow(this.items[0]);
      }
    },
    hightlightRow(row) {
      this.selectedCode = row[this.rowKey];
      this.$set(row, 'selected', true);
    }
  },
  mounted() {
    // Select the first item in the list of items (if there are any)
    // and highlight it.
    this.highlightFirst();
  },
...