行分组算法¶
统计信息:字数 3925 阅读8分钟
Model 数据层分组算法¶
行数据结构
let rows = [
{_id: '01', '0000': 'a', '1111': 2, '2222': 102},
{_id: '02', '0000': 'a', '1111': 2, '2222': 100},
{_id: '03', '0000': 'b', '1111': 1, '2222': 102},
{_id: '04', '0000': 'b', '1111': 3, '2222': 100},
{_id: '05', '0000': 'b', '1111': 5, '2222': 100},
{_id: '06', '0000': 'b', '1111': 3, '2222': 100},
{_id: '07', '0000': 'b', '1111': 5, '2222': 100},
];
分组数据结构,每一项是行的键,表示用这些键分组
let group_bys = ['0000', '1111', '2222'];
基本思路:根据每一层分组条件进行递归,然后把新的子分组放在父分组中。
多层分组并不是线性的,是多层级的树状结构,那么尝试把数组转换成树状结构,然后递归树。
function runNode(node = {}, rows, depth) {
const column_key = group_bys[depth];
// 如果已经到最下层,那么就是叶子树
if (!column_key) {
return rows;
}
let dict = [];
// 遍历当前子树的全部节点,使用字典分组
rows.forEach(row => {
let value = row[column_key];
// 如果当前子分组没有这个键,那么新建这个子分组
if (!dict[value]) {
dict[value] = [];
}
dict[value].push(row);
});
// 设置当前节点的深度
node.depth = depth;
// 现在字典构建完毕,然后转换成树节点
for (let key in dict) {
node[key] = runNode(node[key], dict[key], depth + 1);
}
return node;
}
let root = {};
const initDepth = 0;
root = runNode(root, rows, initDepth);
console.log(root);
上面分组的实际结果数据结构,这样就把数组转换成需要的树状结构
{
"depth": 0,
"a": {
"2": {
"100": [
{
"1111": 2,
"2222": 100,
"_id": "02",
"0000": "a"
}
],
"102": [
{
"1111": 2,
"2222": 102,
"_id": "01",
"0000": "a"
}
],
"depth": 2
},
"depth": 1
},
"b": {
"1": {
"102": [
{
"1111": 1,
"2222": 102,
"_id": "03",
"0000": "b"
}
],
"depth": 2
},
"3": {
"100": [
{
"1111": 3,
"2222": 100,
"_id": "04",
"0000": "b"
},
{
"1111": 3,
"2222": 100,
"_id": "06",
"0000": "b"
}
],
"depth": 2
},
"5": {
"100": [
{
"1111": 5,
"2222": 100,
"_id": "05",
"0000": "b"
},
{
"1111": 5,
"2222": 100,
"_id": "07",
"0000": "b"
}
],
"depth": 2
},
"depth": 1
}
}
View 视图层渲染算法¶
视图渲染分成两个思路
- 所有的行都是同级,使用绝对定位,然后设置不同的 top 值,好处是便于执行行动画。分组的背景框做成一个DIV,在一个层级中。全部的行在另一个层级中。当分组变化时,分组的框直接变化,然后不同的行重新设置 top 值,这样界面上显示行动画效果更好。
- 所有的行都是块级元素,直接把树结构,渲染成块级结构,但是动画效果不好实现。
不同的深度 depth 左侧的偏移量和背景色是不同的
Last update:
November 9, 2024