业务场景
昨天产品小姐姐告诉老王,列表数据增加二级列表,跟服务端沟通后得知,二级列表数据根据一级列表数据动态调用接口查询获取。查找vxe-table api
得知,vxe-table 设置 tree-config、toggle-tree-expand
,vxe-table-column添加 tree-node
。
特别提醒:vxe-table版本2.x
业务代码如下缩略版:
<template>
<div class="div_main_content">
<div class="table-box">
<vxe-table
resizable
show-footer
show-overflow
height="100%"
ref="mainTable"
:data="tableData"
:auto-resize="true"
show-footer-overflow
show-header-overflow
highlight-hover-row
highlight-current-row
:tree-config="treeConfig"
@toggle-tree-expand="toggleTreeExpand"
>
<vxe-table-column title="" width="60" fixed="left" tree-node> </vxe-table-column>
<!-- 其他列配置代码省略... -->
</vxe-table>
</div>
</div>
</template>
<script>
import { getSalesList, salesStatisticsSub } from '@/axios/api.js';
export default {
name: 'SalesStat',
data() {
return {
tableData: [],
/** 一级行id */
currentRowId: '',
/** 一级行id对应的二级菜单数据 */
childNodeData: [],
/** 存储一级行id对应的二级菜单总数 */
cacheMap: new Map(),
};
},
computed: {
treeConfig() {
return {
children: 'children',
lazy: true,
line: false,
trigger: 'default',
loadMethod: this.loadMethod,
};
},
},
watch: {
childNodeData(children) {
const subNodeCount = children.length;
this.cacheMap.set(this.currentRowId, subNodeCount);
setTimeout(() => {
const targetRows = document.querySelectorAll(`tr[rowid=${this.currentRowId}]`);
this.setChildrenClassName(targetRows[0], subNodeCount);
this.setChildrenClassName(targetRows[1], subNodeCount);
}, 0);
},
},
methods: {
// 设置二级列表类名
setChildrenClassName(rowNode, count) {
if (!rowNode) {
return;
}
rowNode.classList.add('row-selected-parent');
let next = count;
let nextRowNode = rowNode.nextElementSibling;
while (next > 0) {
nextRowNode.classList.add('row-selected-son');
nextRowNode = nextRowNode.nextElementSibling;
next--;
}
},
toggleTreeExpand({ expanded, row }) {
const children = row.children;
this.currentRowId = this.$refs.mainTable.getRowid(row);
if (children && expanded) {
const subNodeCount = this.cacheMap.get(this.currentRowId);
setTimeout(() => {
const targetRows = document.querySelectorAll(`tr[rowid=${this.currentRowId}]`);
this.setChildrenClassName(targetRows[0], subNodeCount);
this.setChildrenClassName(targetRows[1], subNodeCount);
}, 0);
}
},
// 一级列表数据
async getTableData() {
this.cacheMap.clear();
const res = await getSalesList();
if (res.code === 200) {
this.tableData = res.data;
}
},
// 二级列表
loadMethod({ row }) {
const param = { id: row.id };
return new Promise((resolve) => {
// api接口
salesStatisticsSub(param).then((res) => {
resolve(res.data);
this.childNodeData = JSON.parse(JSON.stringify(res.data));
});
});
},
},
};
</script>
<style lang="scss" scoped>
.table-box {
>>> .row-selected-parent {
background-color: rgba(0, 110, 255, 0.06) !important;
}
>>> .row-selected-son {
background-color: rgba(0, 110, 255, 0.03) !important;
}
}
</style>
最终实现效果图
实现原理
根据当前点击的行id
rowId
,调用接口查询该行对应的二级列表个数subNodeCount
,由于二级列表直接插入到当前行的下一行,因此可以通过const targetRows = document.querySelectorAll(
tr[rowid=${rowId}]);
查询到当前行元素,结合subNodeCount
,循环调用let nextRowNode = rowNode.nextElementSibling;
设置二级行类名。
- 由于
document.querySelectorAll
查询的是某一刻的静态节点,无法查询到动态插入后的节点。因此把节点查询放到setTimeout下一个周期的轮询。- 第一次调用接口查询二级列表时,触发
toggleTreeExpand
时,无法获取到row.children
个数,因为在查询接口的过程中已经触发了该事件。因此通过watch去监听二级列表的结果,再查询当前点击行元素,添加类名row-selected-parent
,以及分别给二级列表元素添加类名row-selected-son
- 由于调用某行的二级查询列表后,再次展开及收起时,无法触发查询二级列表的接口,因此需要把当前行对应的二级列表个数
subNodeCount
存储下来,通过cacheMap来进行存储及获取
,下次展开时重新给一级列表和二级列表添加类名。
马后炮
- 突然的某一天,我的一个同事跟我说,vxe-table二级菜单展开设置背景颜色,有API的,经过仔细查阅确实如此,害得我绞尽脑汁儿又掉了2根头发。哎,发量减少。
- 设置row行样式:官方API参考链接
- 具体实现方式如下:
<vxe-table
border
:row-class-name="rowClassName"
:data="tableData">
<vxe-table-column type="seq" width="60"></vxe-table-column>
<vxe-table-column field="name" title="Name"></vxe-table-column>
<vxe-table-column field="sex" title="Sex"></vxe-table-column>
<vxe-table-column field="age" title="Age"></vxe-table-column>
<vxe-table-column field="attr1" title="Attr1"></vxe-table-column>
<vxe-table-column field="address" title="Address" show-overflow></vxe-table-column>
</vxe-table>
methods: {
rowClassName ({ row }) {
if (row.hasRowGreen) {
return 'row-green';
}
},
}
- 实现原理是:对于某些想要添加背景颜色的行,在调用接口拿到数据后,给每条想要设置背景颜色的数据,添加自定义属性,比如
item.hasRowGreen = true
;某行有这个属性的row会添加上自定义类型row-green
,在style中定义好类名对应的背景颜色即可。perfect
,完美解决!