超级表格组件之render抽象
0.问题
抽象一个复杂表格组件
1.解决方法
借助element自己的renderHeader与上面的大佬写的render函数,可以抽象出来这样一个组件
// tableCom.vue
<template> <div> <el-table empty-text="暂无数据" ref="table" :data="tableList" border stripe fit highlight-current-row :height="inTableHeight" @selection-change="selectionChange" @row-click="rowClick" :header-cell-style="{ background: 'rgb(1, 97, 90)', color: 'white' }" > <!-- 选择框 --> <el-table-column v-if="select" type="selection" fixed="left" width="55" align="center" /> <template v-for="(itm, idx) in header"> <!-- 特殊处理列 --> <el-table-column v-if="itm.render && !itm.children" :key="idx" :renderHeader="itm.renderHeader ? itm.renderHeader : null" :prop="itm.prop ? itm.prop : null" :label="itm.label ? itm.label : null" :width="itm.width ? itm.width : null" :sortable="itm.sortable ? itm.sortable : false" :align="itm.align ? itm.align : 'center'" :fixed="itm.fixed ? itm.fixed : null" :show-overflow-tooltip="itm.tooltip" min-width="50" > <template slot-scope="scope"> <ex-slot :render="itm.render" :row="scope.row" :index="scope.$index" :column="itm" /> </template> </el-table-column> <!-- 二级表头 --> <el-table-column :key="idx" v-if="itm.children" :label="itm.label ? itm.label : null" header-align="center" :renderHeader="itm.renderHeader ? itm.renderHeader : null" > <el-table-column v-for="(child, indexNum) in itm.children" :key="indexNum" :renderHeader="child.renderHeader ? child.renderHeader : null" :prop="child.prop ? child.prop : null" :label="child.label ? child.label : null" :width="child.width ? child.width : null" :sortable="child.sortable ? child.sortable : false" :align="child.align ? child.align : 'center'" :fixed="child.fixed ? child.fixed : null" :show-overflow-tooltip="child.tooltip" min-width="50" > <template slot-scope="scope"> <ex-slot :render="child.render" :row="scope.row" :index="scope.$index" :column="child" /> </template> </el-table-column> </el-table-column> <!-- 正常列 --> <el-table-column v-if="!itm.render && !itm.children" :key="idx" :renderHeader="itm.renderHeader ? itm.renderHeader : null" :prop="itm.prop ? itm.prop : null" :label="itm.label ? itm.label : null" :width="itm.width ? itm.width : null" :sortable="itm.sortable ? itm.sortable : false" :align="itm.align ? itm.align : 'center'" :fixed="itm.fixed ? itm.fixed : null" :formatter="itm.formatter" :show-overflow-tooltip="itm.tooltip" min-width="50" /> </template> </el-table> </div> </template> <script> // 自定义内容的组件 var exSlot = { functional: true, props: { row: Object, render: Function, index: Number, column: { type: Object, default: null, }, }, render: (h, context) => { const params = { row: context.props.row, index: context.props.index, }; if (context.props.column) params.column = context.props.column; return context.props.render(h, params); }, }; export default { components: { exSlot }, props: { tableList: { type: Array, default: () => [], }, header: { type: Array, default: () => [], }, select: { type: Boolean, default: () => false, }, height: { type: [Number, String, Function], default: () => null, }, }, data() { return { inTableHeight: null, }; }, created() { //该阶段可以接收父组件的传递参数 this.inTableHeight = this.height; console.log("slot see", this.$slots); // 看看里面有啥 }, mounted() { this.$nextTick(() => { //表格高度自适应浏览器大小 this.changeTableHight(); if (!this.height) { window.onresize = () => { this.changeTableHight(); }; } }); }, destroyed() { //高度自适应事件注销 window.onresize = null; }, watch: { /** * 数据变化后 高度自适应 */ tableList() { this.$nextTick(() => { this.changeTableHight(); }); }, }, methods: { /** * 选择框选择后更改,事件分发 */ selectionChange(selection) { this.$emit("selection-change", selection); }, /** * 点击事件 */ rowClick(row, column, event) { this.$emit("row-click", row, column, event); }, /** * 高度自适应 * 当表格展示空间小于460按460px展示,大于的时候高度填充 */ changeTableHight() { if (this.height) { //如果有传进来高度就取消自适应 this.inTableHeight = this.height; this.$refs.table.doLayout(); return; } let tableHeight = window.innerHeight || document.body.clientHeight; //高度设置 let disTop = this.$refs.table.$el; //如果表格上方有元素则减去这些高度适应窗口,66是底下留白部分 tableHeight -= disTop.offsetTop + 26; if (disTop.offsetParent) tableHeight -= disTop.offsetParent.offsetTop; this.inTableHeight = tableHeight < 460 ? 460 : tableHeight; //重绘表格 this.$refs.table.doLayout(); }, }, }; </script> <style> .changeColorYellow { color: rgb(206, 206, 169); } </style>
2.使用
// testPage.vue
普通表格内容的使用
二级表头使用
3.补充——其他版本的render抽象
上代码
// lineCom.vue
<template> <div class="lineCom"> <template v-for="(itm, idx) in header"> <div v-if="itm.render" :key="idx"> <ex-slot :render="itm.render" :column="itm" /> </div> </template> </div> </template> <script> // 自定义内容的组件 var exSlot = { functional: true, props: { row: Object, render: Function, index: Number, column: { type: Object, default: null, }, }, render: (h, context) => { // const params = { // row: context.props.row, // index: context.props.index, // }; // if (context.props.column) params.column = context.props.column; return context.props.render(h, context.props.column); }, }; export default { components: { exSlot }, props: { header: { type: Array, default: () => [], }, }, }; </script>
// lineComTable.js
// 使用
人生到处知何似,应似飞鸿踏雪泥。