表格效果
根据官网的例子不使用jsx,实现结构
<template>
<div class="table-container">
<el-auto-resizer>
<template #default="{ width }">
<el-table-v2
class="table"
:columns="columns"
:data="data"
:width="width"
:height="height"
scrollbar-always-on
@scroll="handleScroll"
>
<template #row="props">
<Row v-bind="props" />
</template>
</el-table-v2>
</template>
</el-auto-resizer>
</div>
</template>
根据官网的例子,使用了autoSize组件获取宽度,只做宽度自适应
scrollbar-always-on 让滚动条一直显示
监听组件scroll事件,滚动到底部时加载更多数据
设置组件入参和数据状态
const props = defineProps({
data: {
type: Array,
defuault: () => [],
},
columns: {
type: Array,
defuault: () => [],
},
});
const emit = defineEmits(["scrollToBottom"]);
分别是列数据和表格数据,列数据和表格数据由父组件传入
并定义滚动到底部的抛出事件
let height = 500;
设置宽度为500
function handleScroll(e) {
if (height - 50 + e.scrollTop >= 50 * data.length - 1) {
emit("scrollToBottom");
}
}
定义函数,滚动到底部时,给父组件发布自定义事件
样式改写
<style scoped lang="scss">
.table-container {
padding: 20px 35px;
.table {
width: 100%;
}
}
::v-deep(.el-table-v2__row-cell) {
height: calc(100% - -2px);
}
::v-deep(.el-table-v2__header-cell) {
height: calc(100% - -1px);
background: #f6f6f6;
border-right: 0 !important;
border-bottom: 0 !important;
}
::v-deep(.el-table-v2__body) {
border-bottom: 1px solid #eee;
border-left: 1px solid #eee;
}
::v-deep(.el-vl__vertical) {
right: 0;
}
</style>
table-v2的样式没有v1版本的丰富,提供的属性也不够详细,只能手动修改,修改了边框和滚动条的位置
单元格合并操作
let { columns, data } = props;
let mergeColumns = [0, 1];
columns.forEach((item, i) => {
item.style = {
borderRight: "1px solid #eee",
borderBottom: "1px solid #eee",
justifyContent: "center",
};
if (mergeColumns.includes(i)) {
item.rowSpan = function ({ rowData, rowIndex, cells, columns }) {
let maxNum = columns[i - 1]?.rowSpan?.({ rowData, rowIndex, cells, columns });
let { key } = item;
let num = 0;
for (let i = rowIndex; i < data.length; i++) {
if (data[rowIndex][key] !== data[i][key]) {
return maxNum ? Math.min(num, maxNum) : num;
} else {
num++;
}
}
return num;
};
}
});
const Row = ({ rowData, rowIndex, cells, columns }) => {
for (let i = 0; i < columns.length; i++) {
const rowSpan = columns[i].rowSpan?.({ rowData, rowIndex, cells, columns });
if (rowSpan > 1 && rowIndex <= data.length) {
Object.assign(cells[i].props.style, {
backgroundColor: "var(--el-color-white)",
height: `${rowSpan * 50}px`,
alignSelf: "flex-start",
zIndex: rowSpan,
});
}
}
return cells;
};
合并原理:
将需要合并的第一个单元格,调整其样式和层级,让第一个单元格把其他需要合并的其他单元格覆盖
实现方式:
-
先对列数据进行操作,改写样式,将内容居中并在每一格加上border,让样式与table-v1的样式相同
-
定义需要进行合并单元格的列,第几列需要做合并,就要将合并方法添加至第几列的方法添加至组件中
-
实现合并方法,找到该单元格中,后面与其内容相同的单元格
单元格高度 = 单元格基础高度 * 与其内容相同单元格数量
单元格层级 = 与其内容相同单元格数量