关于js树形方法封装的心得
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div class="app"></div> </body> <script> let Arr=[ { id: '1', menu_name: '设置', menu_url: 'setting', parent_id: 0 }, { id: '1-1', menu_name: '权限设置', menu_url: 'setting.permission', parent_id: '1' }, { id: '1-1-1', menu_name: '用户管理列表', menu_url: 'setting.permission.user_list', parent_id: '1-1' }, { id: '1-1-2', menu_name: '用户管理新增', menu_url: 'setting.permission.user_add', parent_id: '1-1' }, { id: '1-1-3', menu_name: '角色管理列表', menu_url: 'setting.permission.role_list', parent_id: '1-1' }, { id: '1-2', menu_name: '菜单设置', menu_url: 'setting.menu', parent_id: '1' }, { id: '1-2-1', menu_name: '菜单列表', menu_url: 'setting.menu.menu_list', parent_id: '1-2' }, { id: '1-2-2', menu_name: '菜单添加', menu_url: 'setting.menu.menu_add', parent_id: '1-2' }, { id: '2', menu_name: '订单', menu_url: 'order', parent_id: 0 }, { id: '2-1', menu_name: '报单审核', menu_url: 'order.orderreview', parent_id: '2' }, { id: '2-2', menu_name: '退款管理', menu_url: 'order.refundmanagement', parent_id: '2' } ] console.log(Arr) const t0 = performance.now(); let treeList = Arr.reduce((prev, cur) => { prev[cur['id']] = cur; return prev }, {}) console.log(treeList) //通过引用类型原理实现 let result = Arr.reduce((prev, cur) => { let pid = cur.parent_id; // pid为0的就找不到父对象,找到当前cur的父对象 // 对象的浅拷贝,引用关系存在,在后面处理parent的时候也会导致cur的改变,达到递归的效果 let parent = treeList[pid] // console.log(parent,1) // 如果父对象存在,就将cur压到父对象的children属性中 if (parent) { // parent和cur存在引用关系 parent.children ? parent.children.push(cur) : parent.children = [cur] } else if (pid === 0) { // 没有父对象,则此cur为树的根元素 prev.push(cur) } return prev }, []) const t1 = performance.now(); console.log(t1 - t0, 'milliseconds'); console.log(result) function toTree2(data) { let result = []; let obj = {}; data.forEach(item => { obj[item.id] = Object.assign(item, obj[item.id] || {}); if (item.parent_id) { let parent = obj[item.parent_id] || {}; parent.child = parent.child || []; parent.child.push(item); obj[item.parent_id] = parent; } else { result.push(obj[item.id]) } }) return result; } const t3 = performance.now(); console.log(toTree2(Arr)) const t4 = performance.now(); console.log(t4 - t3, 'milliseconds'); function toTree3(items) { const result = []; // 存放结果集 const itemMap = {}; // for (const item of items) { const id = item.id; const parent_id = item.parent_id; if (!itemMap[id]) { itemMap[id] = { children: [], } } itemMap[id] = { ...item, children: itemMap[id]['children'] } const treeItem = itemMap[id]; if (parent_id === 0) { result.push(treeItem); } else { if (!itemMap[parent_id]) { itemMap[parent_id] = { children: [], } } itemMap[parent_id].children.push(treeItem) } } return result; } const t5 = performance.now(); console.log(toTree3(Arr)) const t6 = performance.now(); console.log(t6 - t5, 'milliseconds'); </script> </html>
三种不同封装方式,性能有很大差异,可以自己在本地跑起来测试