跳到主要内容

列表和树转化

数据

let list = [
{
id: 1,
pid: 0,
title: '首页'
},
{
id: 2,
pid: 0,
title: '招生管理'
},
{
id: 100,
pid: 2,
title: '开班计划'
},
{
id: 101,
pid: 2,
title: '意向客户'
},
{
id: 102,
pid: 2,
title: '客户列表'
},
{
id: 3,
pid: 0,
title: '系统管理'
},
{
id: 103,
pid: 3,
title: '用户管理'
},
{
id: 104,
pid: 3,
title: '部门管理'
},
{
id: 105,
pid: 3,
title: '部门管理'
},
{
id: 4,
pid: 0,
title: '信息管理'
},
{
id: 106,
pid: 4,
title: '信息类型'
},
{
id: 1001,
pid: 106,
title: '发布信息'
}
];

1.递归处理无限子级数据

console.log(formateDataTree(list));

function formateDataTree(data) {
let parents = data.filter(item => item.pid === 0),
children = data.filter(item => item.pid !== 0);
dataToTree(parents, children);
return parents;
function dataToTree(parents, children) {
parents.forEach(p => {
children.forEach((c, i) => {
if (c.pid === p.id) {
let _children = JSON.parse(JSON.stringify(children));
_children.splice(i, 1);
dataToTree([c], _children);
if (p.children) {
p.children.push(c);
} else {
p.children = [c];
}
}
});
});
}
}

2.非递归扁平化处理

console.log(formateDataTree(list));
function formateDataTree(data) {
let _data = JSON.parse(JSON.stringify(data));
return _data.filter(p => {
const _arr = _data.filter(c => c.pid === p.id);
_arr.length && (p.children = _arr);
return p.pid === 0;
});
}

3.reduce

console.log(formateDataTree(list));

function formateDataTree(data) {
// info 为对象,以每一项的 id 为 key, 并且为每个对象添加 children 属性
let info = data.reduce((acc, cur, idx) => {
return (acc[cur.id] = cur), acc;
}, {});
return data.filter(item => {
// 将非根节点的 info 下的 item 继续遍历 —— 为当前项寻找父节点
if (info[item.pid]) {
// info[0]不存在, 并且还找到该节点的父节点
// 将对应的 item 放入对应的对象里面去,因为它是浅拷贝,所以会影响原来的数组,进而组装成一个树结构
// 将 pid 相同的项,全部 push 到
if (info[item.pid].children) {
info[item.pid].children.push(item);
} else {
info[item.pid].children = [item];
}
}
// 将 pid 为 0 的 item 返回
return !item.pid;
});
}

获取指定元素的所有父级对象的索引

/**
* 获取指定元素的所有父级对象的索引
* @param {array} treeData - 要匹配的树
* @param {string} $selectKey - 要匹配的元素
* github: https://github.com/chenyin151/GetParentForTree
*/
export const getParentForTree = (treeData, $selectKey) => {
for (let i = 0; i < treeData.length; i++) {
const layer = 0;
const posIndx = [];
const item = treeData[i];
if (item.value === $selectKey) {
return [{ value: item.value, label: item.label }];
} else {
const res = scanTree(item, $selectKey, layer, posIndx);
if (res) return res;
}
}
};

/**
* 扫描树下面的孩子对象
* @param {object} $item - 要递归遍历的对象
* @param {string} $value - 要匹配的元素
* @param {number} $layer - 遍历到哪一级孩子对象
* @param {array} $posIndx - 用来存储匹配到的元素的所有父级
* @returns {array} - 匹配到的元素的所有父级
*/
const scanTree = ($item, $value, $layer, $posIndx) => {
if (!$item.children) {
$layer -= 1;
return false;
}
$posIndx[$layer] = { value: $item.value, label: $item.label };
for (let i = 0; i < $item.children.length; i++) {
const item = $item.children[i];
if (item.value === $value) {
$posIndx.push({ value: item.value, label: item.label });
return $posIndx;
} else {
const layer = $layer + 1;
const node = scanTree(item, $value, layer, $posIndx);
if (!node && $posIndx.length > 0) {
$posIndx.length -= 1;
$posIndx[$layer] = { value: $item.value, label: $item.label };
}
if (node) return node;
}
}
};

在子级的 value 添加父级的 value

/**
* 在子级的value添加父级的value
* @param {array} sources
* @return {array} sources
*/
export const formateTreeSelect = sources => {
if (Object.prototype.toString.call(sources) !== '[object Array]') {
return [];
}
let result = sources;
for (let item of result) {
if (item.children) {
addKeys(item.children, item.value);
}
}
return result;
};

/**
* 在子级的value添加父级的value
* @param {array} children
* @param {string} pValue
*/
const addKeys = (children, pValue) => {
for (let subItem of children) {
subItem.value = `${pValue}-${subItem.value}`;
let subKey = subItem.value;
if (subItem.children) {
addKeys(subItem.children, subKey);
}
}
};

Tree 转为 List

/**
* 返回 Tree 的数据 转换为 Array 数据格式
* @param {array} nodes - Tree
* @return {array} arr - Array
*/
export const formatListData = nodes => {
let arr = [];
function fn(tree) {
for (let i = 0; i < tree.length; i++) {
arr.push(tree[i].key);
if (tree[i].children && tree[i].children.length > 0) {
fn(tree[i].children);
}
}
}
fn(nodes);
return arr;
};

tree 改变键值

/**
* Tree 改变键值
* @param {array} data
* @param {string} newTitle
* @param {string} newKey
* @param {string} oldTitle
* @param {string} oldKey
* @return {array} treeData
*/
export const formatTreeData = (arr, newTitle, newKey, oldTitle, oldKey) => {
let treeData = [];
for (let i = 0; i < arr.length; i++) {
let item = {
[newKey]: arr[i][oldKey],
[newTitle]: arr[i][oldTitle]
};
if (arr[i].children && arr[i].children.length > 0) {
item.children = formatTreeData(arr[i].children, newTitle, newKey, oldTitle, oldKey);
}
treeData.push(item);
}
return treeData;
};