JavaScript层级树结构构建求助:双数组数据格式化问题
问题:无法生成指定层级结构的员工树状列表
我需要实现展示员工层级关系的树结构,已有可运行的JavaScript代码,但由于数据来自staffMembers(员工数据)和categories(部门分类)两个独立数组,存在数据匹配和层级渲染的问题,无法生成如下指定格式的层级列表:
<ul> <li>Terry Cats - Chief Creative Officer: Executive <ul> <li>Nick Thompson - Head of Design: Operations <ul> <li>Nick Jenson - Intern designer: Interns</li> </ul> </li> </ul> </li> <li>Bruce Davids - Chief Strategy Officer: Executive <ul> <li>David Smith - Head of Development: Operations</li> <li>John Jones - Head of Marketing: Operations</li> </ul> </li> <li>Bill Bass - Chief Executive Officer: Executive</li> </ul>
现有代码
const staffMembers = [ { "_id" :0, "name" : "David", "surname" : "Smith", "slug": "david-smith", "category" : "operations", "title": "Head of Development", "reportsTo": "bruce-davids" }, { "_id" :1, "name" : "John", "surname" : "Jones", "slug": "john-jones", "category" : "operations", "title": "Head of Marketing", "reportsTo": "bruce-davids" }, { "_id" :3, "name" : "Nick", "surname" : "Thompson", "slug": "nick-thompson", "category" : "operations", "title": "Head of Design", "reportsTo": "terry-cats" }, { "_id" :4, "name" : "Nick", "surname" : "Jenson", "slug": "nick-jenson", "category" : "interns", "title": "Intern designer", "reportsTo": "nick-thompson" }, { "_id" :6, "name" : "Terry", "surname" : "Cats", "slug": "terry-cats", "category" : "c-suite", "title": "Chief Creative Officer", "reportsTo": "" }, { "_id" :7, "name" : "Bruce", "surname" : "Davids", "slug": "bruce-davids", "category" : "c-suite", "title": "Chief Strategy Officer", "reportsTo": "" }, { "_id" :8, "name" : "Bill", "surname" : "Bass", "slug": "bill-bass", "category" : "c-suite", "title": "Chief Executive Officer", "reportsTo": "" } ] const categories = [ { "_id" :0, "name" : "Executive", "parent" : "", "slug" : "c-suite" }, { "_id" :1, "name" : "Operations", "parent" : "c-suite", "slug" : "operations" }, { "_id" :2, "name" : "Interns", "parent" : "operations", "slug" : "interns" }, ]; const hierarchy = (data) => { const tree = []; const childOf = {}; let results = []; let cat = ""; let childrens = []; data.forEach((item,index) => { const { slug, reportsTo, category } = item; // console.log(category); childOf[slug] = childOf[slug] || []; item.children = childOf[slug]; reportsTo ? (childOf[reportsTo] = childOf[reportsTo] || []).push(item) : tree.push(item); // if(category == categories.slug ){ cat = category; const indexs = categories.findIndex(object => { return object._id; }); // } }); for(let i = 0;i < tree.length;i++){ for(let j = 0;j < tree[i].children.length;j++){ childrens = (tree[i].children[j]); } results.push(tree[i].name + " " + tree[i].surname + " - " + tree[i].title +": " + cat + '*' + childrens.name + " " + childrens.surname + " - " + childrens.title + ": " + "cat"+cat); } return results; };
解决方案
现有代码的核心问题:
- 未正确将员工的
category字段(slug值)映射到categories数组中的显示名称(比如c-suite对应Executive) - 层级渲染逻辑仅处理了一层子节点,无法递归生成多层嵌套结构
- 字符串拼接逻辑固定,无法适配动态的员工层级
修正后的代码如下:
// 先创建category的slug到名称的映射,方便快速查找 const categoryMap = categories.reduce((map, cat) => { map[cat.slug] = cat.name; return map; }, {}); // 递归生成层级HTML的函数 function generateEmployeeTreeHTML(employees) { if (!employees.length) return ''; let html = '<ul>'; employees.forEach(emp => { // 获取员工对应的分类名称 const categoryName = categoryMap[emp.category] || emp.category; // 拼接当前员工的li内容 html += `<li>${emp.name} ${emp.surname} - ${emp.title}: ${categoryName}`; // 如果有子节点,递归生成子节点的HTML if (emp.children && emp.children.length) { html += generateEmployeeTreeHTML(emp.children); } html += '</li>'; }); html += '</ul>'; return html; } // 主函数:构建员工树状结构并生成HTML const buildHierarchy = (staffData) => { const tree = []; const childMap = {}; // 第一步:构建员工的树状结构 staffData.forEach(emp => { // 给每个员工添加children属性 emp.children = childMap[emp.slug] || []; if (emp.reportsTo) { // 如果有上级,把当前员工加入上级的children列表 if (!childMap[emp.reportsTo]) { childMap[emp.reportsTo] = []; } childMap[emp.reportsTo].push(emp); } else { // 没有上级的是根节点,加入tree数组 tree.push(emp); } }); // 第二步:递归生成HTML return generateEmployeeTreeHTML(tree); }; // 调用函数生成HTML并插入页面(示例) const hierarchyHTML = buildHierarchy(staffMembers); console.log(hierarchyHTML); // 如果要插入到页面,可以用 document.getElementById('container').innerHTML = hierarchyHTML;
代码说明
- categoryMap:通过
reduce方法把categories数组转换成键值对,键是slug,值是分类名称,这样可以O(1)时间获取员工对应的分类显示名。 - generateEmployeeTreeHTML:递归函数,接收员工数组,生成对应的
<ul>和<li>结构,遇到有子节点的员工时,递归调用自身生成子层级。 - buildHierarchy:先遍历员工数据,构建出带有
children属性的树状结构,根节点是没有reportsTo的员工,然后调用递归函数生成完整的HTML。
运行修正后的代码,就能生成你需要的层级列表结构。
内容的提问来源于stack exchange,提问作者Fabrice Ibols
相关产品推荐
相关产品推荐

