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>