在给定 CSS 选择器的情况下查找 DOM 元素的 Vanilla JavaScript 函数

Posted

技术标签:

【中文标题】在给定 CSS 选择器的情况下查找 DOM 元素的 Vanilla JavaScript 函数【英文标题】:Vanilla JavaScript function to find DOM elements given a CSS selector 【发布时间】:2019-11-25 17:23:50 【问题描述】:

我需要编写一个函数,它接受一个 CSS 选择器作为参数,并返回一个匹配这个选择器的 DOM 元素数组。我必须遵守一些规则。

我无法使用任何 JS 库。 我无法使用 querySelector/querySelectorAll。

我有多种测试 CSS 选择器,我需要这些选择器来测试我的功能。我想我可以通过简单的标签名称、类名称或 ID 名称。然后我可以做一些 if/else 语句并调用 document.getElementsByTag/Class/ID 等来获取元素。

function answer (selector) 
    if (selector.indexOf(".") >= 0)
        return document.getElementsByClassName(selector)
    else if (selector.indexOf("#") >= 0)
        return document.getElementById(selector)
    else 
        return document.getElementsByTagName(selector)

我现在的问题是,如果单个查询中有多个选择器。例如,我不确定如何处理选择器$div.a_class#an_id。我的想法是在每个 .或 # 然后逐个链接搜索每个选择器的文档,但似乎你不能这样做。任何帮助或指导将不胜感激。

【问题讨论】:

您需要支持哪些 CSS 功能? CSS-selectors 规范长达 95 页。那里有很多深奥的东西 - 例如。伪类、子组合子、属性、逻辑组合等等。但是...您可以查看sizzlejs.com 的来源,看看他们在做什么 【参考方案1】:
function $(selector) 
  var element = [];
  for (let select of document.body.children) 
    if (select.matches(selector)) 
      element.push(select);
    
  
  return element;

【讨论】:

【参考方案2】:

一种选择是递归搜索文档的.children,并检查被迭代的元素.matches是否是选择器。如果是,则将其推送到数组中:

const find = (selector, parent=document, arr=[]) => 
  [...parent.children].forEach((child) => 
    if (child.matches(selector)) 
      arr.push(child);
    
    find(selector, child, arr);
  );
  return arr;
;

console.log(find('div.a_class#an_id'));
<div>
  <div class="a_class" id="an_id">target!</div>
</div>

【讨论】:

以上是关于在给定 CSS 选择器的情况下查找 DOM 元素的 Vanilla JavaScript 函数的主要内容,如果未能解决你的问题,请参考以下文章

原生Js操作DOM

使用 Selenium 提取元素的 CSS 选择器

[ jquery 过滤器 prevUntil([exp|ele][,fil]) ] 此方法用于在选择器的基础之上搜索查找当前元素之前所有的同辈元素,直到遇到匹配的那个元素为止

带有 css 邻接选择器的响应式 flexbox 设计

jQuery之常用DOM操作

如何为 DOM 元素生成唯一的 CSS 选择器?