单元格合并
设计思路
- 接管 Table.Column 的 render 事件,通过设置 rowSpan 来合并单元格
- 在数据刷新后事件中,遍历数据并计算列的合并数,记录在 spanCount 计算列中,用于设置列的 rowSpan
运行效果如下
1. 在 table 对应的 data 组件中增加一个计算列 spanCount(数据类型:文本)
2. 在 .w 页面的 data.js 中加入以下代码,并修改 initSpanCount 函数的 spanCols 数组,指定要合并的列名
// 初始化计算列 spanCount,在 data 的 onAfterRefresh 事件中调用
initSpanCount(data) {
// spanCols 指定要合并的列,支持多列,列的合并数会记录在计算列 spanCount
let spanCols = ["fDescription"];
/* firstRow 在数据遍历计算时记录合并的首行、值、合并数
firstRow = {
col1: {
firstRow:
value:
count:
}
}
*/
let firstRow = {};
// 解析并写入计算列 spanCount = "{col1:2,col2:0}"
function setSpanCount(row, col, count) {
let spanCount = {};
if (row.spanCount) {
spanCount = JSON.parse(row.spanCount);
}
spanCount[col] = count;
data.setValue("spanCount", JSON.stringify(spanCount), row);
}
// 遍历数据
data.each(function(params){
let row = params.row;
for (let i = 0; i < spanCols.length; i++) {
let spanCol = spanCols[i];
let value = row[spanCol];
if (firstRow[spanCol] && (value == firstRow[spanCol].value)) {
// 如果当前列的值在 firstRow 已存在,首行的合并数 + 1,当前行的合并数 = 0
firstRow[spanCol].count = firstRow[spanCol].count + 1;
setSpanCount(row, spanCol, 0);
} else {
// 如果当前列的值在 firstRow 不存在
if (firstRow[spanCol]) {
// 记录前一个值的首行合并数
setSpanCount(firstRow[spanCol].firstRow, spanCol, firstRow[spanCol].count)
}
// 开始记录下一个值的首行
firstRow[spanCol] = {
"firstRow": row,
"value": value,
"count": 1
}
}
}
})
// 遍历后记录最后的首行
for (let i = 0; i < spanCols.length; i++) {
let spanCol = spanCols[i];
setSpanCount(firstRow[spanCol].firstRow, spanCol, firstRow[spanCol].count)
}
}
3. 在 data 的刷新后事件中调用 initSpanCount 初始化 spanCount
如果数据有增删改查变动会影响合并计算,需要在对应事件中再次调用 initSpanCount,这个函数只会遍历数据并重新计算 spanCount,没有其他副作用
onRestData0AfterRefresh(event){
let data = event.source;
this.initSpanCount(data);
}
4. 进入.w页面源码,找到需要合并的column,增加如下的customRender属性
customRender="{columnRender}"
将restData0和fDescription改为自己的数据组件ID和列名,增加render属性后的XML大致如下
<antdv:Table.Column xmlns:attr="http://www.wex5.com/attr" class="column" customRender="{columnRender}" dataIndex="fDescription" id="tableColumn0" width="120px">
<attr:title id="default0">
<antdv:Typography.Text content="说明" id="typographyText0"/>
</attr:title>
<attr:render id="default6"/>
</antdv:Table.Column>
**注意:这个列中不能放置其他组件,即
<attr:render id="render4" />
里面必须是空的**
到这里列已经可以自动按内容合并了,如果需要垂直居中,继续下面的操作
5. 在.w的js中定义columnRender函数的实现
import { reactive, ref, watch } from "vue";
import { usePage, useData } from "vue_addon/core";
let $page = usePage();
let restData = useData("restData0");
// 获取指定行列的合并数
let getRowSpan = (row, col)=>{
let spanCount = restData.getValue("spanCount", row);
let rowSpan = 1;
if (spanCount) {
rowSpan = JSON.parse(spanCount)[col];
}
return rowSpan;
}
let columnRender=({text, record, index, column})=>{
return {
children: text,
props: {
rowSpan: getRowSpan(record, column.dataIndex)
}
};
}
完成