保姆级教程:Ant Design Vue中 a-table 嵌套子表格

news2025/2/23 23:56:27

前端为Ant Design Vue 版本为1.6.2,使用的是vue2

Ant Design Vue中 a-table 嵌套子表格,说的可能稍微墨迹了点,不过重点内容都说的比较详细,利于新人理解,高手可以自取完整代码

内容概述:

  • 完成样式及完整代码展示
  • 子表格嵌套
  • 只打开一个嵌套表格

完成样式及完整代码展示

下图为官网图,会在每行最前面多一个加号,点击后会展开,看到子表格的数据
在这里插入图片描述

<template>
  <div>
    <a-card>
      <a-table :columns="columns" :data-source="datasource"  :bordered="true"  :expandedRowKeys="expandedRowKeys" 
        @expand="getInnerData" :pagination="pagination">
        <a-table slot="expandedRowRender" slot-scope="text" :columns="innerColumns" :data-source="inndata"
          :pagination="false"></a-table>
        <span slot="operation" slot-scope="text, record">
          <a-button type="primary" icon="unordered-list" @click="getData(record)">
            详情
          </a-button>
        </span>
      </a-table>
    </a-card>
  </div>
</template>
<script>
import { axios } from '@/utils/request'

const columns = [
  {
    title: '序号',
    dataIndex: 'id',
    key: 'id',
  },
 。。。。。中间省略
  {
    title: '操作',
    key: 'operation',
    width: '80px',
    scopedSlots: { customRender: 'operation' },
  },
];

const innerColumns = [
   {
    title: '子表单列',
    dataIndex: 'XXX',
    key: 'XXX',
  },
];

const inndata = [];

export default {
  data() {
    return {
      datasource: [],
      columns,
      innerColumns,
      inndata,
      expandedRowKeys:[],
      pagination: {
        //分页
        showSizeChanger: true, //是否分页
        curPageSizeIndex: 0,
        pageSize: 10, //一页显示多少条
        // total: 1, //总条数
        current: 1, //当前显示页面
        pageSizeOptions: ['10', '20', '30'],
        showTotal: (total) => `共计 ${total}`, //显示总数
        onShowSizeChange: (current, pagesize) => {
          this.pagination.current = current
          this.pagination.pageSize = pagesize
          this.options.offset = (current - 1) * pagesize
          this.options.limit = pagesize
          this.refreshData()
        },
        onChange: (current, pageSize) => {
          this.pagination.current = current
          this.options.offset = (current - 1) * pageSize
          this.options.limit = pageSize
          this.refreshData()
        },
      },
    }
  },

  mounted() {
    this.refreshData()
  },
  methods: {
    refreshData() {
      axios({
        url: 'url',
        method: 'post',
      }).then((res) => {
        if (res.errCode > 0) {
          this.$notification.error({
            message: '错误信息',
            description: res.errMsg,
          })
          return
        }
        console.log(res, '数据')
        this.datasource = res
      })
    },
    
    getInnerData(expanded, record) {
      this.expandedRowKeys=[]
      if (expanded) { 
        var b = ''
        b=(record.id-1).toString()
        this.expandedRowKeys.push(Number(b.slice(-1)))
        this.inndata = [];
        this.inndata.push(this.datasource[record.id - 1])
      }
    },

    getData(record) {
      console.log(record);
    },

  },
}
</script>
<style scoped>
</style>

子表格嵌套

子格嵌套从代码层简单理解就是一个<a-table></a-table>中套了一个<a-table></a-table>,即<a-table><a-table></a-table></a-table>,当然,这只是一个简单理解,并不是这样写,要在其中添加一些东西。
抛开一些配置项,解释下:

<template>
  <div>
    <a-card>
    // 这里开始是父表格组件,columns -> 父级列名,datasource -> 父级表中的数据, @expand="getInnerData" -> 点开子表单的操作函数,pagination -> 分页的设置
      <a-table :columns="columns" :data-source="datasource"  
        @expand="getInnerData" :pagination="pagination">
        // 这里开始是子表格组件,slot="expandedRowRender" 重点,必须有,innerColumns-> 子级列名,inndata-> 子级表中的数据,
        <a-table slot="expandedRowRender" slot-scope="text" :columns="innerColumns" :data-source="inndata"
          :pagination="false"></a-table>// 这里是子表格组件结尾
          // 这里是父表格span,不用的可以删掉
        <span slot="operation" slot-scope="text, record">
          <a-button type="primary" icon="unordered-list" @click="getData(record)">
            详情
          </a-button>
        </span>
      </a-table>// 这里是父表格组件结尾
    </a-card>
  </div>
</template>
<script>
// 数据请求axios 
import { axios } from '@/utils/request'

// 设置父级列名
const columns = [
  {
    title: '序号',
    dataIndex: 'id',
    key: 'id',
  },
 。。。。。中间省略
  {
    title: '操作',
    key: 'operation',
    width: '80px',
    scopedSlots: { customRender: 'operation' },
  },
];

// 设置子级列名
const innerColumns = [
   {
    title: '子表单列',
    dataIndex: 'XXX',
    key: 'XXX',
  },
];

// 设置子级数据,写下面data里也行
const inndata = [];

export default {
  data() {
    return {
      datasource: [],
      columns,
      innerColumns,
      inndata,
      pagination: {
        //分页
        showSizeChanger: true, //是否分页
        curPageSizeIndex: 0,
        pageSize: 10, //一页显示多少条
        // total: 1, //总条数
        current: 1, //当前显示页面
        pageSizeOptions: ['10', '20', '30'],
        showTotal: (total) => `共计 ${total}`, //显示总数
        onShowSizeChange: (current, pagesize) => {
          this.pagination.current = current
          this.pagination.pageSize = pagesize
          this.options.offset = (current - 1) * pagesize
          this.options.limit = pagesize
          this.refreshData()
        },
        onChange: (current, pageSize) => {
          this.pagination.current = current
          this.options.offset = (current - 1) * pageSize
          this.options.limit = pageSize
          this.refreshData()
        },
      },
    }
  },

  mounted() {
  // 进入页面直接运行的函数
    this.refreshData()
  },
  methods: {
  // 异步请求获取数据
    refreshData() {
      axios({
        url: 'url',
        method: 'post',
      }).then((res) => {
        if (res.errCode > 0) {
          this.$notification.error({
            message: '错误信息',
            description: res.errMsg,
          })
          return
        }
        console.log(res, '数据')
        // 将数据赋值给父级表格
        this.datasource = res
      })
    },
    
      // 点开子级表格(就是点击那个加号)触发的函数
    getInnerData(expanded, record) {
    // 判断是否点开
      if (expanded) { 
      // 点开后执行。。。
      // 先将子级表格数据清空,否则之前点开别的行的数据也会在里面
        this.inndata = [];
        // 再将父级点击的那一行的数据(record)给子级数据存进去,具体情况根据自己需求更改
        this.inndata.push(record)
      }
    },
// 点击父级表格表格span,也就是那个“详情”按钮触发的函数
    getData(record) {
      console.log(record);
    },

  },
}
</script>
<style scoped>
</style>

通过上述操作会发现能够实现基本的子表格嵌套,但是会发现点开一个子表单后,再点一个,两个都会打开,但是里面的子表格数据是相同的,这就是个很大的问题,为了解决这个问题,请看下面,这个在官网没直接写出来,API里有相关的参数,现在告诉你应该怎样操作

只打开一个嵌套表格

为了防止点开多个子表格内容相同,再结合我自己的使用场景,我只需要展开一个子表格就行,也就是说点开新的子表格后,原来的子表格自动关闭
下面把需要改动的代码片段给你们:
1. 父级中的修改内容

   // 添加  :expandedRowKeys="expandedRowKeys"   目的是使expandedRowKeys只有最新点开子表单的key
	<a-table :columns="columns" :data-source="datasource"  :bordered="true"  :expandedRowKeys="expandedRowKeys" 
        @expand="getInnerData" :pagination="pagination">
        <a-table slot="expandedRowRender" slot-scope="text" :columns="innerColumns" :data-source="inndata"
          :pagination="false"></a-table>
        <span slot="operation" slot-scope="text, record">
          <a-button type="primary" icon="unordered-list" @click="getData(record)">
            详情
          </a-button>
        </span>
     </a-table>

2. 在data里加上空的 expandedRowKeys

export default {
  data() {
    return {
      datasource: [],
      columns,
      innerColumns,
      inndata,
      // 添加空的expandedRowKeys
      expandedRowKeys:[],
      。。。。。。

3. 修改getInnerData函数

 getInnerData(expanded, record) {
    // 先将expandedRowKeys数据清空
      this.expandedRowKeys=[]
      if (expanded) { 
        //  将父级的第几条数据传到expandedRowKeys里,我这用的是数据表里的id处理的,我的id是从1开始
        //  我这是一页十条数据,要放入0-9,第一条是0,第十条是9,一定要是数字格式
        //  再一个,注意下,假设使用的是数据中的第45条,record.id=45
        //  但是传入 expandedRowKeys 只能是0-9,且是数字格式,那么应该将数字4传到expandedRowKeys中
        //  因为record.id=45这条数据,在表格中的第五行,应该是4
        //  所以有了下面的record.id-1,再转成字符串格式,取最后一位,再转成数字
        //  也有人用key,id能够获取到,不过我没弄成功,就这样吧,实现功能就行
        var b=(record.id-1).toString()
        this.expandedRowKeys.push(Number(b.slice(-1)))
        
        //  下面两行说过,我就把注释直接粘过来了
        // 先将子级表格数据清空,否则之前点开别的行的数据也会在里面
        this.inndata = [];
        // 再将父级点击的那一行的数据(record)给子级数据存进去,具体情况根据自己需求更改
        this.inndata.push(record)
      }
    },

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/405896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在收到消息后秒级使网站变灰,不改代码不上线,如何实现?

注意&#xff1a;文本不是讲如何将网站置灰的那个技术点&#xff0c;那个技术点之前汶川地震的时候说过。 本文不讲如何实现技术&#xff0c;而是讲如何在第一时间知道消息后&#xff0c;更快速的实现这个置灰需求的上线。 实现需求不是乐趣&#xff0c;指挥别人去实现需求才…

[Vue warn]: Error in render: “TypeError: Cannot read properties of undefined(reading“category1Name“

明明页面正常显示&#xff0c;但是控制台却一直报 如下 错误 [Vue warn]:渲染错误:"TypeError:无法读取未定义的属性(读取category1Name)" 中发现的 Detail 的 vuex 仓库 import { reqDetail } from "/api" export default{actions:{async getDetail({co…

【前端修炼场】 — 这些标签你学会了么?快速拿下 “hr”

此文为【前端修炼场】第四篇&#xff0c;上一篇文章链接&#xff1a;上一篇 文章目录前言一、 常用标识符1.1 特殊标识符1.1.1 "<" 和 ">"&#xff08;<&#xff1b;&#xff09;1.1.2 空格&#xff08;&emsp&#xff1b;&#xff09;1.1.3 商…

uniapp微信小程序无法使用本地静态资源图片,背景图在真机不显示方法

前言 首先要说明&#xff0c;使用HBuilder或者vs Code工具开发的时候&#xff0c;在微信开发者工具调试的时候&#xff0c;我们使用本地图片是OK的&#xff0c;但是一旦放到真机上调试的时候&#xff0c;图片就显示不出来。 先看uniapp官网对背景图片的说明 错误用法 <tem…

uniapp 微信小程序和H5的弹窗滚动穿透解决

滚动穿透&#xff1a; 页面里的弹窗也是可以滚动的&#xff0c;然后页面本身内容多所以也是滚动的&#xff0c;就造成&#xff0c;在弹窗滚动的时候&#xff0c;页面内容也跟着滚动了。如图所示 ps: 电脑端分鼠标滚轮滚动和长按鼠标拖拽滚动&#xff0c;手机端只有触屏滑屏滚…

视频实时行为检测——基于yolov5+deepsort+slowfast算法

文章目录前言一、核心功能设计二、核心实现步骤1.yolov5实现目标检测2.deepsort实现目标跟踪3.slowfast动作识别三、核心代码解析1.参数2.主函数3.将结果保存成视频总结前言 前段时间打算做一个目标行为检测的项目&#xff0c;翻阅了大量资料&#xff0c;也借鉴了不少项目&…

【Java】运算符

我不去想是否能够成功 既然选择了远方 便只顾风雨兼程 —— 汪国真 目录 1. 认识运算符 1.1 认识运算符 1.2 运算符的分类 2. 算术运算符 2.1 四则运算符 2.2 复合赋值运算符 2.3 自增 / 自减 运算符 3.关系运算符 4.逻辑运算符 4.1 逻辑与 && 4.2 逻…

什么是异步

文章目录 前言一、异步是什么&#xff1f;二、举个例子来理解异步 1.异步最典型的例子就是“回调函数”总结前言 在vue的过程中&#xff0c;我们一定会遇到诸如&#xff1a; function&#xff08;参数&#xff09;.then(res>{}) 形式的代码。到底怎么编译执行的呢 &#xf…

【Jetpack】ViewModel 架构组件 ( 视图 View 和 数据模型 Model | ViewModel 作用 | ViewModel 生命周期 | 代码示例 | 使用注意事项 )

文章目录一、Activity 遇到的问题二、视图 View 和 数据模型 Model三、ViewModel 架构组件作用四、ViewModel 代码示例1、ViewModel 视图模型2、Activity 组件3、UI 布局文件4、运行效果五、ViewModel 生命周期六、ViewModel 使用注意事项一、Activity 遇到的问题 Activity 遇到…

宝塔部署nodejs项目

前言 部署操作很简单&#xff0c;网上也有很多教程&#xff0c;不过我还是踩坑了&#xff0c;这里记录一下&#xff0c;给其他人也避避坑吧。 步骤 首先你已经有了服务器&#xff0c;并且打开了宝塔面板&#xff0c;其次准备好你的nodejs项目。 在宝塔安装pm2管理器&#xf…

Nginx 调整文件上传大小限制

使用3A服务器做了网页&#xff0c;感觉挺不错的&#xff0c;使用LNMP环境 用Nginx部署了前端&#xff0c;发现上传附件大一点就会报错&#xff0c;查看配置文件&#xff0c;发现spring的附件配置已经配置了。那么就看下Nginx的body设置。nginx文件上传默认是1MB。 在 server 模…

VUE3TS: Vue3+TS的项目搭建

简介 通过 Vue-cli4 创建的 Vue3TS 的项目&#xff0c;并进行一些基础使用的举例。 此例是以 VSCode编辑器 进行的编码。 一、项目搭建 1. 进入命令提示符窗口 在要搭建项目的文件夹中&#xff0c;点击路径&#xff0c;输入CMD并按回车 2. 查看node版本、Vue-cli版本 2…

Android 架构之长连接技术

上文中我们提到了HttpDNS&#xff0c;虽然它比系统DNS更优&#xff0c;但终归还是要做DNS操作。而长连接都是IP直接连接&#xff0c;因此没有DNS相关的开销和耗时。 3. 如果有大量网络请求&#xff0c;可以明显减少网络延时&#xff0c;节省带宽 对于大型App而言&#xff0c;…

npm——安装、卸载与更新

npm 官方文档&#xff1a;https://docs.npmjs.com/ 什么是npm npm&#xff08;“Node 包管理器”&#xff09;是 JavaScript 运行时 Node.js 的默认程序包管理器。 它也被称为“Ninja Pumpkin Mutants”&#xff0c;“Nonprofit Pizza Makers”&#xff0c;以及许多其他随机…

Vue通知提醒框(Notification)

项目相关依赖版本信息 可自定义设置以下属性&#xff1a; 自动关闭的延时时长&#xff08;duration&#xff09;&#xff0c;单位ms&#xff0c;默认4500ms消息从顶部弹出时&#xff0c;距离顶部的位置&#xff08;top&#xff09;&#xff0c;单位像素px&#xff0c;默认24p…

WebSocket开发(心跳监测)功能

前言 在之前的文章中完成了客服对话的Demo功能&#xff0c;但是现在的连接是无限制的长时间连接没有做心跳、失活、超时断连等功能&#xff0c;心跳的实现方法有很多种&#xff0c;并且WebSocket就提供了ping/pong类型的消息。 心跳的触发方式也分两种&#xff1a; 客户端触…

微信小程序实现图片上传

前言 手机上传图片的功能大家一定都用过吧&#xff0c;今天教你用微信小程序实现这个小功能。 实现效果如下&#xff1a; 实现思路&#xff1a; 首先我们需要定义一个存放图片的数组&#xff0c;通过方法拿取图片的详细信息&#xff0c;然后调用微信小程序的 wx.uploadFile 方…

element ui datepicker时间控件实现范围选择周,季,年。

因项目要求&#xff0c;需日&#xff0c;周&#xff0c;月&#xff0c;季&#xff0c;年五种日期范围选择器&#xff0c;故参考文章&#xff08;在末尾&#xff09;后分享 一.效果图 二、版本及下载 1.实现需要修改源码&#xff0c;目前修改的版本为2.15.3&#xff0c;所以想要…

Vue3路由配置createRouter、createWebHistory、useRouter,useRoute

目录 手动配置Vue-router环境&#xff1a; 组件内部跳转路由、传参useRouter,useRoute Vue3和Vue2基本差不多&#xff0c;只不过需要将createRouter、createWebHistory从vue-router中引入&#xff0c;再进行使用。 手动配置Vue-router环境&#xff1a; 1、下载包&#xff1a…

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘result‘)

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading result) 如题所示问题&#xff0c;耽误三天寻找bug&#xff0c;终于在我睡意朦胧之际发现了一道光&#xff0c;发现 await 出现的三个点&#xff1a; 于是打开 findAllCategory()这个函数 对应…