修复 el-table二次封装-兼容无限级嵌套表头,内容使用作用域插槽的bug

修复 el-table二次封装-兼容无限级嵌套表头,内容使用作用域插槽的bug

问题出现原因:因为使用组件引用自身实现无限嵌套表头,导致父传子的作用域在孙组件下不会渲染

在后续文章再写如何实现

修复后代码

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" :scopedSlotList="scopedSlotList">
              <template v-slot:[key]="{ row, column, $index }" v-for="(value, key) in $scopedSlots">
                <slot :name="key" v-bind="{ row, column, $index }"></slot>
              </template>
            </nestColumn>
          </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,
    },
  },
  data () {
    return {
      scopedSlotList: {}
    }
  },
  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 v-slot:[key]="{ row, column, $index }" v-for="(value, key) in $scopedSlots">
          <slot :name="key" v-bind="{ row, column, $index }"></slot>
        </template>
      </nestColumn>
    </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>

<style></style>

使用

<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>
      <template #age1="{ row }">
        <el-button type="primary"> {{ row.age1 }}</el-button>
      </template>
      <template #addressA="{ row }">
        <span style="color: red;"> {{ row.addressA }}</span>
      </template>
      <template #phoneF="{ row }">
        <span style="color: pink;"> {{ row.phoneF }}</span>
      </template>
    </renderTable>
    <div style="height: 20px; ">

    </div>
    <son>
      <template #sonSlot="{ msg }">
        <p style="color: red;">{{ msg }}</p>
      </template>
      <template #grandsonSlot="{ msg }">
        <p style="color: green;">{{ msg }}</p>
      </template>
    </son>
    <!-- <p style="color: green;">{{ msg }}</p> -->
  </div>
</template>

<script>
import son from "./son.vue"
export default {
  components: {
    son
  },
  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, slot: true }] },
        {
          prop: "info",
          label: "个人信息",
          width: 300,
          children: [
            {
              prop: "phone",
              label: "手机号",
              children: [
                {
                  prop: "phoneA", label: "手机号A", children: [
                    {
                      prop: "phoneC", label: "手机号C",
                    },
                    { prop: "phoneD", label: "手机号D" },
                  ]
                },
                {
                  prop: "phoneB", label: "手机号B", children: [
                    {
                      prop: "phoneE", label: "手机号E",
                    },
                    { prop: "phoneF", label: "手机号F", slot: true },
                  ]
                },
              ],
            },
            {
              prop: "address",
              label: "联系地址",
              children: [
                { prop: "addressA", label: "地址A", slot: true },
                { prop: "addressB", label: "地址B" },
              ],
            },
          ],
        },
        { prop: "nation", label: "民族", width: 200 },
        { prop: "merry", label: "婚姻状况", width: 200, slot: true },
      ]),
    }
  },
  methods: {
    getList () { },
  },
}
</script>

<style></style>

效果

在这里插入图片描述

成果

实现了只需要在组件传入作用域插槽内容,即可供其所有后代组件使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值