vue+render实现el-table多表头

一、前言

又好久没更新文章了。。补一篇,主要分享封装多表头表格render函数实现多表头表格

在公司维护低代码平台,有个需求需要通过拖拽配置一个多表头的表格(element的el-table),但是发现网上好像没什么资料,特别是平台是通过render函数实现的,对这个还不是很熟悉,摸索着写出来了,分享一下

二、Render函数代码

首先说明一下,用render函数纯粹是为了拖拽组件以及配置字段后之后可以即时预览,真正开发还是使用公用的表格组件

这部分代码是公用的,多个组件都用这一个,我稍微改了改

import columns from './multi-table'
export default {
	render(h) {
		// 深拷贝一份出来
		const confClone = deepClone(this.conf)
		// 准备 h 函数的第三个参数, 也就是子节点
		const children = columns(h, confClone)
		const dataObject = {
			attrs: {},
			props: {},
			nativeOn: {},
			on: {},
			style: {}
		}
		// 将json表单配置转化为vue render可以识别的"数据对象(dataObject)"
		Object.keys(confClone).forEach(key => {
			const val = confClone[key]
			if (key === '__vModel__') {
				// 双向绑定v-model
				dataObject.props.value = confClone.__config__.defaultValue
				dataObject.on.input = val => {
					this.$emit('input', val)
				}
			} else if (dataObject[key]) {
				dataObject[key] = {
					...dataObject[key],
					...val
				}
			} else {
				dataObject.attrs[key] = val
			}
		})

		return h('el-table', dataObject, children)
	},
	props: ['conf']
}

columns函数

/**
 * 递归渲染子节点
 * @param {Object} item
 */
function renderChildren(h, item) {
    // 递归出口
	if (!item.children || item.children.length == 0) {
		return [h('el-table-column', {
			props: {
				label: item.label
			}
		})];
	} else {
        // 核心在这里,递归调用
		let arr = item.children.map(item => renderChildren(h, item));
		return h('el-table-column', {
			props: {
				label: item.label
			}
		}, arr);
	}
}
export default {
	columns(h, conf) {
		const list = [];
		// 针对每一个columns渲染一个el-table-columns
		conf.__slot__.columns.forEach(item => {
			list.push(renderChildren(h, item));
		});
		return list
	}
}

三、附录

1. 多表头表格组件

每个公司的业务不同,我只贴核心部分

<el-table>
	<!-- index列 -->
	<el-table-column v-if="showIndex" type="index" width="50"></el-table-column>
	<!-- selection列 -->
	<el-table-column v-if="showSelection" type="selection" width="55"></el-table-column>
	<!-- 解决列错乱问题,因为el-table不支持嵌套除了el-table-column的组件 -->
	<el-table-column width="1"></el-table-column>
	<!-- 渲染列, 支持多级表头 -->
	<LRTableColumn v-for="(column, cindex) in filterColumns()" :key="cindex" :column="column"></LRTableColumn>
	<!-- 自定义操作列 -->
	<el-table-column v-if="customBtn.display" :min-width="100" label="操作" fixed="right">
		<template slot-scope="scope">
			<span v-for="(bColumn, bindex) in customBtn.btnColumns" :key="bindex">
				<Button v-if="!scope.row.children" type="info" :icon="bColumn.icon" size="small"
					@click="bColumn.function(scope.row)" ghost>{{ bColumn.label }}</Button>
			</span>

			<Button v-if="customBtn.doubleEdit" type="info" size="small" @click="beginWithButtonEdit(scope)"
				ghost>编辑</Button>
			<Button v-if="customBtn.doubleEdit" type="info" size="small" @click="endWithButtonEdit(scope)"
				ghost>完成</Button>
		</template>
	</el-table-column>
</el-table>

LRTableColumn代码

<template v-if="!column.children || column.children.length == 0">
	<el-table-column :prop="column.field" :label="column.title" :min-width="column.width" :formatter="formatter">
		<template slot-scope="scope">
			<!-- 根据自己的需求进行 -->
		</template>
	</el-table-column>
</template>
<!-- 递归渲染多级表头 -->
<template v-else>
	<el-table-column :label="column.title">
		<!-- 子表头 -->
		<LRTableColumn v-for="(sub, index) of column.children" :key="index" :column="sub"></LRTableColumn>
	</el-table-column>
</template>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值