antd 表格展开行里的内容组件使用表格,数据覆盖问题

129 篇文章 3 订阅
21 篇文章 0 订阅
1、点击展开当前行,使用当前行的对象渲染基本的信息,使用当前行的id请求获取展开行里的表格数据

在这里插入图片描述

2、问题来了:点击第一个展开获取到的数据是正常的,点击第二个,获取到的表格数据会覆盖第一个表格的数据,即最新点击获取的展开行的表格数据覆盖前面打开的行的表格数据

在这里插入图片描述

3、代码:
父组件:
<a-table
  :columns="columns"
  :dataSource="dataSource"
  :row-selection="{
    selectedRowKeys: selectedRowKeys,
    onChange: onSelectChange,
  }"
  :pagination="pagination"
  rowKey="id"
  :loading="dataLoad"
  @change="onChange"
  @expand="getDeviceData"
>
  <span slot="action" slot-scope="record">
    <a @click="addNew(true, record)">修改 </a>|
    <a @click="deleteRecord(record.id)">删除 </a>
  </span>
  <template slot="expandedRowRender" slot-scope="record">
    <device-content
      ref="detail"
      :records="record"
      :tableData="tableData"
    />
  </template>
</a-table>
// 展开行
async getDeviceData(expanded, record) {
  if (expanded) {
    this.getDeviceFn(record.id)
  }
},
// 获取关联的设备数据
async getDeviceFn(id) {
  let res = await this.$http(
    this.$url.GET_ALL_RELATION_DEVICE_DATA + id,
    "get"
  );
  if (res.data.code === 200) {
    let { data } = res.data;
    this.tableData = data;
  }
},

子组件:
<div class="desBm">
  <a-table
    :columns="columns"
    :dataSource="$attrs.tableData"
    rowKey="id"
    :pagination="false"
  >
    <span slot="action" slot-scope="records">
      <a href="javascript:void(0);" @click="goDevice(records.deviceCode)">查看设备</a>
    </span>
  </a-table>
</div>
4、展开的时候,给最外层表格数据添加属性,属性的值就是子组件的表格数据,使用延迟改变子组件tableShow的值,也可以实现需求(弊端:数据量大、网络不好时、延迟的时间不好定义,不严谨)
父组件:
<template slot="expandedRowRender" slot-scope="record">
  <device-content
    ref="detail"
    :records="record"
  />
</template>
// 展开行
async getDeviceData(expanded, record) {
  if (expanded) {
    let index = 0
    this.dataSource.forEach((t,i)=>{
      t.id==record.id ? index = i : ''
    })
    record.tableData = await this.getDeviceFn(record.id);
    this.$set(this.dataSource , index, record)
  }
},
// 获取关联的设备数据
async getDeviceFn(id) {
  let res = await this.$http(
    this.$url.GET_ALL_RELATION_DEVICE_DATA + id,
    "get"
  );
  if (res.data.code === 200) {
    let { data } = res.data;
    return data;
  }else{
    return []
  }
},

子组件:
<div class="desBm" v-if="tableShow">
  <a-table
    :columns="columns"
    :dataSource="records.tableData"
    rowKey="id"
    :pagination="false"
  >
    <span slot="action" slot-scope="records">
      <a href="javascript:void(0);" @click="goDevice(records.deviceCode)">查看设备</a>
    </span>
  </a-table>
</div>
mounted() {
  setTimeout(() => {
    console.log(this.records.tableData)
    this.tableShow = true;
  }, 1000);
},
5、解决一: 拿到最外层表格的数组时,添加一个属性并赋值tableShow: false,在展开行的时候,给当前行的tableShow: true, 通过this.$set更新当前行数据,子组件表格通过判断这个属性再渲染,完整代码:
父组件:
<template slot="expandedRowRender" slot-scope="record">
  <device-content
    ref="detail"
    :records="record"
  />
</template>
// 展开行事件
async getDeviceData(expanded, record) {
  if (expanded) {
    let index = 0
    this.dataSource.forEach((t,i)=>{
      t.id==record.id ? index = i : ''
    })
    record.tableData = await this.getDeviceFn(record.id); // 调用获取子组件表格数据的方法
    record.tableShow = true
    this.$set(this.dataSource , index, record)
  }
},
// 获取子组件表格数据
async getDeviceFn(id) {
  let res = await this.$http(
    this.$url.GET_ALL_RELATION_DEVICE_DATA + id,
    "get"
  );
  if (res.data.code === 200) {
    let { data } = res.data;
    return data;
  }else{
    return []
  }
},

子组件deviceContent:
<div class="desBm" v-if="tableShow">
  <a-table
    :columns="columns"
    :dataSource="records.tableData"
    rowKey="id"
    :pagination="false"
  >
    <span slot="action" slot-scope="records">
      <a href="javascript:void(0);" @click="goDevice(records.deviceCode)">查看设备</a>
    </span>
  </a-table>
</div>
props: ['records'],
6、解决二: 子组件使用watch监听父组件传来的值,原理跟第一种相同,就是给响应式的数组添加新属性,通过$set更新数组
父组件:
async getData(query = {}) {
  this.dataLoad = true;
  let res = await this.$http(this.$url.GET_STATION_MANAGE_LIST, "get", {
    pageNum: this.pagination.current,
    pageSize: this.pagination.pageSize,
    ...query,
  }).catch(() => {
    this.dataLoad = false;
  });
  this.dataLoad = false;
  let { data } = res;
  if (data.code == 200) {
    this.dataSource = data.data.rows.map(i=>({...i,tableData:[]})); //  添加属性且赋值tableData: []
    this.pagination.current = data.data.currentPage;
    this.pagination.total = data.data.total;
  }
},
// 展开行
async getDeviceData(expanded, record) {
  if (expanded) {
    let index = 0
    this.dataSource.forEach((t,i)=>{
      t.id==record.id ? index = i : ''
    })
    record.tableData = await this.getDeviceFn(record.id); // 赋值
    this.$set(this.dataSource , index, record);  // 更新
  }
},
// 获取关联的设备数据
async getDeviceFn(id) {
  let res = await this.$http(
    this.$url.GET_ALL_RELATION_DEVICE_DATA + id,
    "get"
  );
  if (res.data.code === 200) {
    let { data } = res.data;
    return data;
  }else{
    return []
  }
},

子组件:
<div class="desBm" v-if="tableShow">
  <a-table
    :columns="columns"
    :dataSource="records.tableData"
    rowKey="id"
    :pagination="false"
  >
    <span slot="action" slot-scope="records">
      <a href="javascript:void(0);" @click="goDevice(records.deviceCode)">查看设备</a>
    </span>
  </a-table>
</div>
data() {
  return {
    columns,
    showImg: false,
    tableShow:false,
  }
},
watch:{
  records:{
    handler: function(val){
      if(val) {
        this.tableShow = true
      }
    },
    deep:true,
    immediate: true
  }
},
7、深入了解vue响应式原理才能更好理解、解决问题! 最终效果:

在这里插入图片描述

不要活在别人的世界里,却也不是自我为中心!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值