bootstrap-vue b-table:在 table 重新加载时保持展开的行展开

bootstrap-vue b-table: keep expanded rows expanded on table reload

其中的 expand/collapse 部分工作得很好。

现在我正在使用 javascript startInterval() 每 2 秒重新加载一次 table。最终这将转移到网络套接字。

一般来说,作为 table load/reload 的一部分,系统通过检查 [=39] 来检查是否应该在详细信息栏中显示图标“^”或“v” =], 这很好用。

getChevron(row, index) {
 if (row.detailsShowing == true) {     
   return "chevronDown";
 }
   return "chevronUp";
}

当用户选择关系列中的“^”图标时,将调用 @click=row.toggleDetails 来展开该行,然后调用函数 v-on:click="toggleRow(row)" 来跟踪用户选择的行.这使用服务器端系统生成的 guid 来跟踪。

在 2 秒内,table 将重新加载并且该行会折叠。在 load/reload 上,在它加载的第一列关系中,我调用函数 checkChild(row),根据我本地存储的数组检查行 guid,以确定这是否是应在加载时扩展的行。

<template #cell(relationship)="row"> {{checkChild(row)}} <\template>

如果行 guid 与数组中的一个匹配,我会尝试设置

checkChild(row){
  var idx = this.showRows.indexOf( row.item.id);
    if(idx > -1){
     row.item.detailsShowing = true;
     row.rowSelected = true;
     row.detailsShowing == true
     row._showDetails = true;
   }
}

并且我能够看到我找到了匹配项,但是 none 设置为 true 的那些变量使展开的行保持打开状态,该行总是在重新加载时折叠

有人对我如何使行在 table 重新加载时保持打开状态有任何想法吗?

您的代码出现问题是因为 Vue 2 警告。在将属性添加到 data 之后向对象添加属性将 而不是 是反应性的。要解决这个问题,您必须使用 Vue.set.

您可以阅读更多相关内容 here

但是,像您在模板中所做的那样调用函数似乎是一种不好的做法。 您应该在获取数据后执行此操作,或者使用诸如计算 属性 之类的东西来进行映射。

这里有两个简化的例子。

API调用后映射

{
  data() {
    return {
      items: [],
      showRows: []
    }
  },
  methods: {
    async fetchData() {
      const { data } = await axios.get('https://example.api')
      foreach(item of data) {
        const isRowExpanded = this.showRows.includes(item.id);
        item._showDetails = isRowExpanded;
      }
      this.items = data;
    }
  }
}

使用计算

{
  computed: {
    // Use `computedItems` in `<b-table :items="computedItems">`
    computedItems() {
      const { items, showRows } = this;
      return items.map(item => ({
        ...item, 
        _showDetails: .showRows.includes(item.id)
      }))
    }
  },
  data() {
    return {
      items: [],
      showRows: []
    }
  },
  methods: {
    async fetchData() {
      const { data } = await axios.get('https://example.api')
      this.items = data;
    }
  }
}

有关更完整的示例,请查看下面的代码段。

const {
  name,
  datatype,
  image
} = faker;

const getUser = () => ({
  uuid: datatype.uuid(),
  personal_info: {
    first_name: name.firstName(),
    last_name: name.lastName(),
    gender: name.gender(),
    age: Math.ceil(Math.random() * 75) + 15
  },
  avatar: image.avatar()
});

const users = new Array(10).fill().map(getUser);

new Vue({
  el: "#app",
  computed: {
    computed_users() {
      const {
        expanded_rows,
        users
      } = this;
      return users.map((user) => ({
        ...user,
        _showDetails: expanded_rows[user.uuid]
      }));
    },
    total_rows() {
      const {
        computed_users
      } = this;
      return computed_users.length;
    }
  },
  created() {
    this.users = users;

    setInterval(() => {
      users.push(getUser());
      this.users = [...users];
    }, 5000);
  },
  data() {
    return {
      per_page: 5,
      current_page: 1,
      users: [],
      fields: [{
          key: "avatar",
          class: "text-center"
        },
        {
          key: "name",
          thClass: "text-center"
        },
        {
          key: "personal_info.gender",
          label: "Gender",
          thClass: "text-center"
        },
        {
          key: "personal_info.age",
          label: "Age",
          class: "text-center"
        }
      ],
      expanded_rows: {}
    };
  },
  methods: {
    onRowClicked(item) {
      const {
        expanded_rows
      } = this;
      const {
        uuid
      } = item;

      this.$set(expanded_rows, uuid, !expanded_rows[uuid]);
    }
  }
});
<link href="https://unpkg.com/bootstrap@4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.css" rel="stylesheet" />

<script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.js"></script>
<script src="https://unpkg.com/faker@5.5.3/dist/faker.min.js"></script>

<div id="app" class="p-3">
  <b-pagination v-model="current_page" :per-page="per_page" :total-rows="total_rows">
  </b-pagination>

  <h4>Table is refresh with a new item every 5 seconds.</h4>
  <h6>Click on a row to expand the row</h6>
  <b-table :items="computed_users" :fields="fields" bordered hover striped :current-page="current_page" :per-page="per_page" @row-clicked="onRowClicked">
    <template #cell(avatar)="{ value }">
      <b-avatar :src="value"></b-avatar>
    </template>
    <template #cell(name)="{ item: { personal_info: { first_name, last_name } }}">
      {{ first_name }} {{ last_name }}
    </template>
    <template #row-details="{ item }">
      <pre>{{ item }}</pre>
    </template>
  </b-table>
</div>