javascript - 如何打印 DOM 对象的选择器

标签 javascript arrays combinations

给定一个像这样的 DOM 结构:

<div>
  <div>
    <span>
      <img/>
      <i>
        <span></span>
        <meter></meter>
      </i>
      <a><span></span></a>
    </span>
  </div>
  <nav>
    <form>
      <input/>
      <button></button>
    </form>
  </nav>
</div>

想知道如何获取它,然后返回所有选择器的平面数组:

[
  'div > div > span > img',
  'div > div > span > i > span',
  'div > div > span > i > meter',
  'div > div > span > a > span',
  'div > nav > form > input',
  'div > nav > form > button'
]

我的尝试没有取得任何成果:

function outputSelectors(array, node) {
  var tag = node.tagName
  array.push(tag)
  for (var i = 0, n = node.children.length; i < n; i++) {
    var child = node.children[i]
    outputSelectors(array, child)
  }
}

outputSelectors([], document.body.children[0])

不知道该去哪里。

最佳答案

一种可能的非递归方法,从顶部(准确地说是根)到底部:

function collectLeafNodePathes(root) {
  const paths = [];
  const selectorParts = [];
  let el = root;
  while (el) {
    const tagName = el.tagName.toLowerCase();
    if (el.childElementCount) {
      selectorParts.push(tagName);
      el = el.firstElementChild;
      continue;
    }

    paths.push(selectorParts.concat([tagName]).join(' > '));
    do {
       if (el.nextElementSibling) {
         el = el.nextElementSibling;
         break;
       }
       el = el.parentNode;
       selectorParts.pop();         
       if (el === root) {
         el = null;
       }
    } while (el);
  }
  return paths;
}

const selectors = collectLeafNodePathes(document.getElementById('xxx'));
console.log(selectors);
<div id="xxx">
  <div>
    <span>
      <img/>
      <i>
        <span></span>
        <meter></meter>
      </i>
      <a><span></span></a>
    </span>
  </div>
  <nav>
    <form>
      <input/>
      <button></button>
    </form>
  </nav>
</div>

不过,最后一部分(do-while 循环)的边缘有点粗糙;对任何改进持开放态度。

我使用了辅助属性( childElementCountfirstElementChildnextElementSibling )来跳过检查文本节点和内容。如果这不是一个选项(由于兼容性原因),那么很容易实现 polyfills 或只是在非元素节点上“倒回”循环。

关于javascript - 如何打印 DOM 对象的选择器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48522673/

相关文章:

javascript - 装饰 Angulars $ExceptionHandler 时如何防止令人讨厌的副作用?

javascript - 将对象数组中的所有数据求和到新的对象数组中

javascript - 如何将新项目推送到现有数组,该数组的值将从前一项中减去 10,直到它接近 0 或 0?

excel - 将排列与组限制和匹配这些的查找值相结合

python - 查找 numpy 数组的所有 n 组(对、三元组、四元组等)

javascript - 无法在 Angular 中插入 url 参数

javascript - 如何使用响应式菜单防止正文滚动

javascript - 如何控制台登录所选索引?

java - 如何在构造函数类中创建数组?

javascript - 将数组拆分为固定的 n 个具有动态大小的 block