背景

DOM节点统计 DOM 的体积过大会影响页面性能,假如你想在用户关闭页面时统计(计算并反馈给服务器) 当前页面中元素节点的数量总和、元素节点的最大嵌套深度以及最大子元素个数, 请用 JS 配合原生 DOM API 实现该需求(不用考虑陈旧浏览器以及在现代浏览器中的兼容性, 可以使用任意浏览器的最新特性;不用考虑 shadow DOM)。

输入输出

  1. {
  2. totalElementsCount: 9,
  3. maxDOMTreeDepth: 4,
  4. maxChildrenCount: 3
  5. }
  6. const root = {
  7. nodeName: 'html',
  8. children: [{
  9. nodeName: 'head',
  10. children: [],
  11. }, {
  12. nodeName: 'body',
  13. children: [
  14. {
  15. nodeName: 'div',
  16. children: [{
  17. nodeName: 'span',
  18. children: []
  19. }]
  20. },
  21. {
  22. nodeName: 'div',
  23. children: [{
  24. nodeName: 'span',
  25. children: []
  26. }, {
  27. nodeName: 'span',
  28. children: []
  29. }, {
  30. nodeName: 'span',
  31. children: []
  32. }]
  33. }
  34. ]
  35. }]
  36. }

方法:递归

  1. // 递归
  2. // 递归中止条件是?没有子节点
  3. function getStandCount(node){
  4. //节点统计 进入方法增加1
  5. let totalElementsCount = 0 ;
  6. let maxDOMTreeDepth = 0;
  7. let maxChildrenCount = 0 ;
  8. if(node.nodeName){
  9. totalElementsCount++;
  10. }
  11. if(node.children && node.children.length){
  12. // 深度 每访问增加children加一 并累计子元素的深度
  13. // 第一次1 递归第二次进入时 假设 没有子节点 得到的深度为0 返回1 正确
  14. // 第一次1 递归第二次进入时 假设有子节点 子节点没有子节点 子节点得到的深度为1(简化逻辑 实际子节点只会返回01两种情况) 也需要进行累加
  15. maxDOMTreeDepth++
  16. maxChildrenCount = node.children.length;
  17. for(let i=0,len = node.children.length;i<len;i++){
  18. let subNode = node.children[i];
  19. const {totalElementsCount:subTotalElmentCount,maxDOMTreeDepth:subMaxDOMTreeDepth,maxChildrenCount:subMaxChildrenCount} = getStandCount(subNode);
  20. // 总节点数计算 情况1 没有子节点 得到的计数为1 情况2 含有子节点 含有子节点会进行再次递归 也能得到子节点的累加
  21. totalElementsCount+=subTotalElmentCount;
  22. maxDOMTreeDepth+= subMaxDOMTreeDepth;
  23. // 含有最多子元素 为当前元素与获取递归子元素的对比即可 取较大值
  24. maxChildrenCount = maxChildrenCount> subMaxChildrenCount? maxChildrenCount:subMaxChildrenCount
  25. }
  26. }
  27. return {
  28. totalElementsCount,maxDOMTreeDepth,maxChildrenCount
  29. }
  30. }