在二次封装 ElementUI 的 Table 时,我希望可以通过配置的方式,来实现多层表头,思路很简单,直接递归表头即可:
<!-- MyTable -->
<el-table>
<template v-for="h in headers">
<MyTableColumn :key="h.prop" :header="h">
<template v-slot="scope">
<slot :name="h.prop" v-bind="scope" />
</template>
</MyTableColumn>
</template>
</el-table>
<!-- MyTableColumn -->
<template>
<!-- 多层 -->
<el-table-column v-bind="header" v-if="header.children && header.children.length > 0">
<template v-for="h in header.children">
<!-- 递归多层 -->
<MyTableColumn :key="h.prop" :header="h" v-if="h.children && h.children.length > 0">
<template v-slot="scope">
<slot :name="h.prop" v-bind="scope" />
</template>
</MyTableColumn>
<el-table-column v-else :key="h.prop" v-bind="h">
<template v-slot="scope">
<slot :name="h.prop" v-bind="scope" />
</template>
</el-table-column>
</template>
</el-table-column>
<!-- 单层 -->
<el-table-column v-bind="header" v-else>
<template v-slot="scope">
<slot :name="h.prop" v-bind="scope" />
</template>
</el-table-column>
</template>
<script>
export default {
name: "MyTableColumn",
props: {
header: Object
}
}
</script>
然后,直接使用:
<MyTable :headers="[
{ label: 'column-1', prop: 'a' },
{ label: 'column-2', children: [
{ label: 'column-2-1', prop: 'a-1' },
{ label: 'column-2-2', children: [
{ label: 'column-2-2-1', prop: 'a-1-1' },
{ label: 'column-2-2-1', prop: 'a-1-2' }
]}
]},
{ label: 'column-3', prop: 'c' },
{ label: 'column-4', prop: 'd' },
]">
<template v-slot:a-1-1="{ row }">
<span>{{ row.data }}</span>
</template>
</MyTable>
此时会发现插槽并没有正确传递到 MyTableColumn 组件中。
为了实现插槽内容,我们需要调整一下封装的插槽内容逻辑,并不能单单的使用 <slot :name="h.prop" v-bind="scope" />
这样的方式,而需要将所有插槽全部传递过去:
<template
v-for="slotName in Object.keys($scopedSlots)"
v-slot:[slotName]="slotData"
>
<slot :name="slotName" v-bind="slotData || {}" />
</template>
我们把所有在递归时使用插槽的地方都用上面的内容替换掉:
<!-- MyTable {L5-L11} -->
<el-table>
<template v-for="h in headers">
<MyTableColumn :key="h.prop" :header="h">
<!-- 传递所有作用域插槽给 TableColumn -->
<template
v-for="slotName in Object.keys($scopedSlots)"
v-slot:[slotName]="slotData"
>
<slot :name="slotName" v-bind="slotData || {}" />
</template>
</MyTableColumn>
</template>
</el-table>
<!-- MyTableColumn -->
<!-- ... other codes -->
<!-- 递归多层 -->
<MyTableColumn :key="h.prop" :header="h" v-if="h.children && h.children.length > 0">
<!-- 传递所有作用域插槽给 TableColumn -->
<template
v-for="slotName in Object.keys($scopedSlots)"
v-slot:[slotName]="slotData"
>
<slot :name="slotName" v-bind="slotData || {}" />
</template>
</MyTableColumn>
<!-- ... other codes -->
此时再尝试效果,发现就正常了。通过 Object.keys($scopeSlots)
的方式,可以将插槽带到每一个需要的层级去。
文章评论