el-table二次封装-兼容无限级嵌套表头

el-table二次封装-兼容无限级嵌套表头

el-table二次封装后续

项目中经常使用封装后的表格

之前封装的表格是写死表头的结构,只能兼容两层表头结构,如果需要兼容多层则需要手动添加结构

在这里插入图片描述

解决方案:

怎么让模板递归渲染 -》利用组件引用自身

renderTable.vue

<template>
  <div id="renderTable">
    <el-table v-bind="$attrs" :data="data" class="table" v-on="$listeners">
      <template #default>
        <el-table-column v-for="item in columns" v-bind="item" :header-align="item.headerAlign || 'center'"
          :align="item.align || 'center'" :key="item.prop">
          <template v-if="item.slot && !item.children" v-slot="{ row, column, $index }">
            <slot :name="item.prop" v-bind="{ row, column, $index }"></slot>
          </template>
          <template v-for="jtem in item.children">
            <nestColumn :item="jtem" />
          </template>
        </el-table-column>
      </template>
    </el-table>
    <Pagination v-if="paging" :listQuery.sync="listQuery" :count.sync="count" v-on="$listeners"></Pagination>
  </div>
</template>

<script>
import nestColumn from "./nestColumn.vue"
export default {
  name: "renderTable",
  inheritAttrs: false,
  components: {
    nestColumn
  },
  props: {
    columns: {
      type: Array,
      required: true,
    },
    data: {
      type: Array,
      required: true,
    },
    paging: {
      type: Boolean,
      default: false,
    },
    listQuery: {
      type: Object,
    },
    count: {
      type: Number,
    },
  },
  methods: {
    dealSlot (obj) {
      let res = this.$deepClone(obj)
      delete res.slot
      return res
    },
  },
}
</script>
<style lang="scss" scoped>
table {
  width: 100%;
}
</style>

nestColumn.vue

<template>
  <el-table-column :header-align="item.headerAlign || 'center'" :align="item.align || 'center'" :key="item.prop"
    v-bind="item.slot ? dealSlot(item) : item">
    <template v-if="item.slot && !item.children" v-slot="{ row, column, $index }">
      <slot :name="item.prop" v-bind="{ row, column, $index }"></slot>
    </template>
    <template v-for="jtem in item.children">
      <nestColumn :item="jtem" />
    </template>
  </el-table-column>
</template>

<script>
export default {
	//name必须写 不然实现不了组件自身引用自身
  name: 'nestColumn',
  props: {
    item: {
      type: Object,
      required: true,
    }
  },
  methods: {
    dealSlot (obj) {
      let res = this.$deepClone(obj)
      delete res.slot
      return res
    },
  },
}
</script>

使用

<template>
  <div class="table">
    <renderTable :data="tableData" :columns="columns" :border="true" :stripe="true" v-loading="loading" :paging="true"
      :listQuery.sync="listQuery" :count.sync="count" @getList="getList">
      <template #order="{ $index }">
        <span> {{ (listQuery.page - 1) * listQuery.limit + $index + 1 }}</span>
      </template>
      <template #sex="{ row }">
        <span> {{ row.sex ? "男" : "女" }}</span>
      </template>
      <template #merry="{ row }">
        <span> {{ row.merry ? "已婚" : "未婚" }}</span>
      </template>
    </renderTable>
  </div>
</template>

<script>
export default {
  data () {
    return {
      listQuery: {
        vagueSearch: "",
        dateArr: [],
        page: 1,
        limit: 12,
      },
      count: 10,
      tableData: [
        {
          id: 1,
          name: "小明",
          sex: "1",
          age: 18,
          age1: 20,
          nation: "汉族",
          phone: "13000000000",
          phoneA: "13000000000A",
          phoneB: "13000000000B",
          phoneC: "13000000000C",
          phoneD: "13000000000D",
          phoneE: "13000000000E",
          phoneF: "13000000000F",
          merry: 0,
          address: "广州市天河区",
          addressA: "广州市天河区A",
          addressB: "广州市天河区B",
        },
      ],
      columns: Object.freeze([
        { prop: "order", label: "序号", width: 150, slot: true },
        { prop: "name", label: "姓名", width: 200 },
        { prop: "sex", label: "性别", width: 200, slot: true },
        { prop: "age", label: "年龄", width: 200, children: [{ prop: "age1", label: "年龄1", width: 200 }] },
        {
          prop: "info",
          label: "个人信息",
          width: 300,
          children: [
            {
              prop: "phone",
              label: "手机号",
              children: [
                {
                  prop: "phoneA", label: "手机号A",
                  children: [
                    {
                      prop: "phoneC", label: "手机号C", children: [
                        { prop: "phoneE", label: "手机号E" },
                        { prop: "phoneF", label: "手机号F" },
                      ]
                    },
                    { prop: "phoneD", label: "手机号D" },
                  ],
                },
                { prop: "phoneB", label: "手机号B" },
              ],
            },
            {
              prop: "address",
              label: "联系地址",
              children: [
                { prop: "addressA", label: "地址A" },
                { prop: "addressB", label: "地址B" },
              ],
            },
          ],
        },
        { prop: "nation", label: "民族", width: 200 },
        { prop: "merry", label: "婚姻状况", width: 200, slot: true },
      ]),
    }
  },
  methods: {
    getList () { },
  },
}
</script>

<style></style>

效果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值