基于 ElTable 组件进行二次封装
创建 BaseTable.vue 文件
<script>
import { Table, TableColumn } from 'element-ui'
// 复制 ElTable 组件中的方法到自身组件,方便外部通过 js api 方式调用
const baseTableMethod = Object.create(null)
Reflect.ownKeys(Table.methods).forEach(key => {
baseTableMethod[key] = function wrapper(...args) {
const { table } = this.$refs
Table.methods[key].apply(table, args)
}
})
const isFunction = fn => typeof fn === 'function'
const createTableColumn = Column => (h, context, columns) => {
return columns.map(column => {
const options = {
attrs: { ...column },
scopedSlots: {}
}
const headerRender = column.headerRender /* 自定义表头内部渲染方法 */
const render = column.render /* 自定义列内部渲染方法 */
if (isFunction(headerRender)) {
options.scopedSlots.header = scoped => {
return headerRender.call(context, context.$createElement, scoped)
}
}
if (isFunction(render)) {
options.scopedSlots.default = scoped => {
return render.call(context, context.$createElement, scoped)
}
}
return h(Column, options)
})
}
export default {
name: 'BaseTable',
props: {
columns: {
type: Array,
default: () => []
},
dataSource: {
type: Array,
default: () => []
}
},
methods: Object.assign({}, baseTableMethod, {}),
render(h) {
// 获取上下文对象
const { context } = this.$vnode
const { columns, dataSource } = this
const options = {
ref: 'table',
attrs: this.$attrs,
props: { data: dataSource },
on: this.$listeners,
scopedSlots: {}
}
const createColumn = createTableColumn(TableColumn)
return h(Table, options, createColumn(h, context, columns))
}
}
</script>
在执行自定义渲染函数时,传入 context.$createElement 目的是解决父组件 style 标签设置 scoped 属性,导致在应用
样式时需要设置::v-deep的问题,效果如下
创建App.vue文件
<template>
<div>
<BaseTable border :columns="columns"></BaseTable>
</div>
</template>
<script>
import BaseTable from "@/components/BaseTable.vue";
export default {
data() {
return {
columns: [
{
label: '序号',
prop: 'id',
headerRender: (h, scoped) => {
return <div style={{ color: 'red' }}>{scoped.column.label}</div>
}
},
{
label: '用户',
prop: 'username'
},
{
label: '操作'
}
]
}
},
components: {
BaseTable
}
}
</script>
<style scoped></style>
最终实现效果: