1.需求
类似excel可以加斜线有双表头,如下图(咱们当时一整个难住,咱们裙裙难受)
2.咱们开始面向百度,找到一个好主意!
上链接
3.可能会有多级表头所有把table封装了一下,所以我没有用插槽来处理斜线,直接用到了多级表头
//表格组件
<template>
<div id="bias-table">
<el-table
ref="table"
v-loading="props.tableConfig.tableLoading"
:data="props.tableData"
:max-height="props.tableConfig.maxHeight || maxHeight"
:show-summary="props.tableConfig.showSummary"
:header-cell-style="methods.handleHeaderCell"
>
<!--我们当时还有一个需求,表格的列是动态的渲染的,所以一定要保证key值的唯一-->
<column-component
v-for="th in props.columnConfig"
:key="th.id"
:column="th"
></column-component>
</el-table>
<div
class="line"
v-if="!props.tableConfig.standard"
:style="{
width: lineWhide + 'px',
transform: 'rotate(' + lineDeg + 'deg)',
}"
></div>
</div>
</template>
<script setup>
import { defineProps } from 'vue';
import { ref, onMounted, nextTick } from 'vue';
import columnComponent from './column.vue';
const props = defineProps({
tableData: {
type: Array,
default: () => [],
},
tableConfig: {
type: Object,
default: () => {
return {
tableLoading: false,
standard: false,
showSummary: true,
};
},
},
columnConfig: {
type: Array,
default: () => [],
},
});
//自定义数据data
const maxHeight = ref(0);
const table = ref(null);
const firstCellClassName = ref(''); //第一个单元格的类名
const firstCellWidth = ref(); //第一个单元格的宽度
const firstCellHeight = ref(0); //第一个单元格的高度
const lineWhide = ref(0); //对角线的宽度
const lineDeg = ref(0); //对角线的角度
onMounted(() => {
nextTick(() => {
// maxHeight.value = window.innerHeight - table.value.$el.offsetTop - 252;
maxHeight.value = window.innerHeight - table.value.$el.offsetTop;
// console.log(maxHeight.value, '最大高度');
});
});
const methods = {
/**
* 设置表头第一个单元格对角线
* @function
*/
handleHeaderCell({ row, column, rowIndex, columIndex }) {
//如果使用的多级表头 就需要判断是第几个表头
if (rowIndex === 0) {
nextTick(() => {
//根据id设置第一个单元格的class类名
firstCellClassName.value = row[0].id;
//获取第一个单元格的宽度,原文说用realWidth,但我获取不到,所以用到了width,目前没出错
firstCellWidth.value = row[0].width;
methods.getElement();
// console.log(firstCellWidth.value, '查看宽度');
});
}
},
getElement() {
//用原生获取第一个单元格的高度
let element = document.getElementsByClassName(firstCellClassName.value)[0];
//我用到的是复合表头,并且高度相同,所以这里的高度是二倍的
firstCellHeight.value = 2 * element.offsetHeight;
// console.log(firstCellHeight.value, '查看高度');
//获取对角线的长度 a²+b²=c²
lineWhide.value = Math.sqrt(
firstCellWidth.value * firstCellWidth.value +
firstCellHeight.value * firstCellHeight.value,
);
// console.log(lineWhide.value, '对角线宽度');
//获取对角线旋转的角度
lineDeg.value =
(Math.atan(firstCellHeight.value / firstCellWidth.value) * 180) / Math.PI;
// console.log(lineDeg.value, '角度');
},
};
</script>
<style lang="scss" scoped>
#bias-table {
position: relative;
.line {
position: absolute;
z-index: 9;
top: 0;
left: 0;
height: 1px;
background-color: #ccc;
transform-origin: left;
}
:deep .el-table {
tr {
height: 20px;
}
thead.is-group > tr:first-child > th:first-child {
text-align: right;
padding: 0;
border-bottom: 0px;
}
thead.is-group > tr:nth-child(2) > th:first-child {
text-align: left;
padding: 0;
}
/*实现表格头数据换行*/
.cell {
/*text-align: center;*/
white-space: pre-line; /*保留换行符*/
}
}
}
</style>
4.column组件封装
<template>
<el-table-column
:label="props.column.label"
:prop="props.column.prop"
:align="props.column.align || 'center'"
:width="props.column.width"
:show-overflow-tooltip="props.column.tooltip || true"
>
<template v-if="props.column.children && props.column.children.length">
<column-component
v-for="item in props.column.children"
:key="item.id"
:column="item"
></column-component>
</template>
<!--这里不可以用v-else-->
<template v-if="!props.column.children" #default="scope">
<span>{{ scope.row[props.column.prop] }}</span>
</template>
</el-table-column>
</template>
<script setup>
import columnComponent from './column';
import { defineProps } from 'vue';
import { ref, onMounted, nextTick } from 'vue';
const props = defineProps({
column: {
type: Object,
default: () => {},
},
});
onMounted(() => {});
const methods = {};
</script>
5.如果有好的方案请告诉我,持续学习!