antd+vue表格实现跨行与插槽

效果如图

后台返回的数据结构是树状结构,注意内嵌的最内层数组不要命名为children,否则antd会自动将表格变为可展开类表格,如果后台定义成了children字段,前端在渲染页面前将字段改名即可

第一步需要先把数组拆分成普通的数组

var data = [
        {
          id: 1,
          name: "小组1",
          list: [
            { id: 101, name1: "111" },
            { id: 102, name1: "222" },
            { id: 103, name1: "333" },
          ],
        },
        {
          id: 2,
          name: "小组2",
          list: [
            { id: 201, name1: "qqq" },
            { id: 202, name1: "www" },
            { id: 203, name1: "aaz" },
          ],
        },
        {
          id: 3,
          name: "小组3",
          list: [
            { id: 301, name1: "aaa" },
            { id: 302, name1: "bbb" },
          ],
        },
      ]
// 假设上面这个数组是后台传给我们的数据
// 接收到数据后将数据拆分

data.forEach((i, index) => {
      i.childLength = i.list.length; // 设置一个字段,即要跨多少行的数值
      i.num = index + 1; // 保留小组的序号
      i.list.forEach((a, index1) => {
         a.childIndex = index1; // 根据childIndex来判断从哪行开始跨
      });
    });
 data = data.flatMap((item) => {
      return item.list.map((listItem) => ({
        webId: item.id, // 由于有两个id,两个id都有各自的用处,需要将最外层的id改个字段名,否则只会保留最内层的id
        ...item, //其他字段保留
        ...listItem, //其他字段保留
      }));
    });





数组拆分完了后,设置表头

export default {
  data() {
    // columns需在data内定义,否则操作栏中的dom元素无法在页面渲染
    const columns = [
      {
        title: "序号",
        dataIndex: "num", // 小组序号
        align: "center",
        width: 60,
        customRender: (text, row) => {
          const obj = {
            children: text, // text即dataIndex所填写的字段值
            attrs: {},
          };
          if (row.childIndex == 0) { // 表示从第一个成员那行开始跨行
            obj.attrs.rowSpan = row.childLength;
          } else {
            obj.attrs.rowSpan = 0;
          }
          return obj;
        },
      },
      {
        title: "小组",
        dataIndex: "name",
        align: "center",
        customRender: (text, row) => {
          const obj = {
            children: text,
            attrs: {},
          };
          if (row.childIndex == 0) {
            obj.attrs.rowSpan = row.childLength;
          } else {
            obj.attrs.rowSpan = 0;
          }
          return obj;
        },
      },
      {
        title: "成员",
        dataIndex: "name1",
        width: 100,
        align: "center",
      },
      {
        title: "职务",
        dataIndex: "name2",
        width: 90,
        align: "center",
      },
      {
        title: "性别",
        dataIndex: "name3",
        align: "center",
      },
      {
        title: "联系方式",
        dataIndex: "name4",
        align: "center",
      },
      {
        title: "备注",
        dataIndex: "name7",
        align: "center",
      },
      {
        title: "操作",
        align: "center",
        width: 200,
        customRender: (text, record) => {
          const obj = {
            children: (
              <div>
                <span
                  class="editBtn"
                  onClick={() => this.editInfo(record.webId)}
                >
                  编辑
                </span>
                <a-popconfirm
                  placement="bottomRight"
                  title="确定删除?"
                  ok-text="确定"
                  cancel-text="取消"
                  onConfirm={() => this.onDelete(record.webId)}
                >
                  <span class="delBtn">删除</span>
                </a-popconfirm>
              </div>
            ),
            attrs: {},
          };
          if (record.childIndex == 0) {
            obj.attrs.rowSpan = record.childLength;
          } else {
            obj.attrs.rowSpan = 0;
          }
          return obj;
        },
      },
    ];
    return {
      data: [
        {
          id: 1,
          name: "小组1",
          list: [
            { id: 101, name1: "111" },
            { id: 102, name1: "222" },
            { id: 103, name1: "333" },
          ],
        },
        {
          id: 2,
          name: "小组2",
          list: [
            { id: 201, name1: "qqq" },
            { id: 202, name1: "www" },
          ],
        },
        {
          id: 3,
          name: "小组3",
          list: [{ id: 301, name1: "aaa" }],
        },
      ],
    };
  },
  mounted(){
    this.getData();
  },
  methods:{
    getData(){
      // 在此处调用接口获取后台的表格数据,并将数据拆分
    },
    editInfo(){
      // 编辑按钮的点击事件
    },
    onDelete(){
      // 删除按钮的点击事件
    },
  },
}

customRender与插槽scopedSlots无法同时设置,所以只能在customRender设置按钮dom元素与点击事件,且columns需在data内定义,如果写在data外,无法渲染dom元素,还会报错[Vue warn]: Error in render: "ReferenceError: h is not defined"

表格的html代码没有什么变化,与官网一致

<a-table
   :columns="columns"
   :data-source="data"
   :pagination="pagination"
   :row-key="(record) => record.id"
   @change="handleTableChange"
>
</a-table>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值