【问题标题】:How to filter elements in vanilla Javascript like in jQuery?如何像 jQuery 一样过滤 vanilla Javascript 中的元素?
【发布时间】:2018-11-08 13:50:36
【问题描述】:

例如,在 jQuery 中,如果我想要所有 <div><p> 元素,我这样做:

var $x = $("p, div");

然后,如果我想要 x 中的所有 <div> 元素,那么我这样做:

var $divs = $x.filter("div");

那么我该如何在原生 JavaScript 中完成这个简单的 filter 事情呢?

例如,要选择所有<div><p>,那么我可以这样做:

var x = document.querySelectorAll("div, p");

但是 vanilla JavaScript 没有 jQuery 那样的过滤功能,所以我不能这样做:

var divs = x.filter("div"); // ERROR

希望有人可以帮助我:-)

提前致谢。

更新

一些 cmets/answers 建议执行类似 .tagName == "DIV" 的操作来查找 div,但是,我想要一个带有字符串选择器的解决方案,例如 jQuery。

原因是因为我还想使用属性、类甚至多个选择器进行过滤,您可以在其中输入逗号。并且字符串选择器必须是动态的。

这意味着,我不知道选择器中的内容。它可以是 "div[foo='asd'], .bar" 或 "#hello, [xx='yy'], p"

所以我不能硬编码 .tagName == "DIV",因为我不知道选择器字符串中的内容。

【问题讨论】:

  • 我不是 100% 确定,但我认为你可以这样做 [anyDomElement].GetElementsByTagName("div")
  • 你打开jQuery核心代码看了一下.filter()方法吗?
  • 为什么不写一个看起来像第一个代码sn-p但实际上是第二个的包装器?
  • 没有“原生”JavaScript 之类的东西......它通常被称为“香草”或 ECMA6 脚本。
  • @MartinZeitler 所以你的意思是ECMAScript ;)

标签: javascript jquery


【解决方案1】:

您可以将Array.filter()Element.matches() 结合使用

var x = document.querySelectorAll("div, p");
var divs = x.filter(y => y.matches("div"));

// for p tags
var paragraphs = x.filter(y => y.matches("p"));

//for both div and p tags
var mix = x.filter(y => y.matches("div, p"));

【讨论】:

  • Element.matches() 效果很好。这个答案的唯一错误是.filter() 不是 NodeList 的方法,因此您必须先将 NodeList 转换为 Array。示例:[...x].filter()
【解决方案2】:

您可以使用matches 函数来检查 CSS 选择器是否与给定元素匹配。

var x = document.querySelectorAll("div, p");
var divs = [];

// Iterate through the elements that the first query selector matched
//  (is a paragraph or a div tag)
for (var elem of x) {
    // Check if the given element matches the second query selector
    //  (is a div tag)
    if (elem.matches('div')) {
        divs.push(elem);
    }
}

这段代码可以写得更简洁(并且使用更现代的代码):

let x = document.querySelectorAll("div, p");
let divs = Array.from(x).filter(elem => elem.matches("div"));

【讨论】:

    【解决方案3】:

    一个非常幼稚的方法:

    function get(selector) {
     const els = document.querySelectorAll(selector);
    
     return {
       selector,
       length: els.length,
       get: i => els[i],
       [Symbol.iterator]: () => els[Symbol.iterator](),
       filter: f => get(selector + ", " + f)
      };
    }
    

    可用作:

    const menus = get(".menu");
    for(const el of menus) console.log(el);
    console.log(menus.filter("div").get(0));
    

    【讨论】:

    • 抱歉menus.filter("div").get(0) 应该回馈什么?
    • @roko 第一个.menudiv
    【解决方案4】:

    querySelectorAll 返回 NodeList 而不是数组。

    您需要将其转换为数组

    var arr = Array.prototype.slice.call(x);
    var divs = arr.filter(el => { return el.tagName == 'DIV' });
    

    【讨论】:

    • 这如何回答“如何复制jQuery的.filter()
    • 对不起,这里假设知识。我更新了我的答案以更完整。我认为将 NodeList 转换为 Array 可以让用户理解 .filter 现在可用。 Anywho,现在使用 .filter() 函数,您可以按标签名称排序。
    • Array.prototype 可以用来代替[] 以避免不必要的数组实例化。
    • const arr = [...document.querySelectorAll("selector")].filter( 等呢
    • 另外,如果你喜欢简写,y 很奇怪。另一方面,el 众所周知...
    【解决方案5】:

    你可以使用Array.filter

    const elems = document.querySelectorAll('p, div');
    const divs = [...elems].filter(e => {
      return e.tagName == 'DIV'
    });
    
    console.log(divs)
    <div id="div1"></div>
    <div id="div2"></div>
    <div id="div3"></div>
    <p id="p1"></p>
    <p id="p2"></p>
    <p id="p3"></p>

    您可以更改 e.tagName 以使用其他内容进行过滤:

    const elems = document.querySelectorAll('p, div');
    
    const divs = [...elems].filter(e => {
      return e.tagName == 'DIV'
    });
    
    const byId = [...elems].filter(e => {
      return e.id == 'div1'
    });
    
    const byClass = [...elems].filter(e => {
      return e.className == 'class1'
    });
    
    console.log(byClass)
    <div id="div1" class="class1"></div>
    <div id="div2" class="class1"></div>
    <div id="div3" class="class2"></div>
    <p id="p1" class="class1"></p>
    <p id="p2" class="class2"></p>
    <p id="p3" class="class2"></p>

    【讨论】:

    • 如何按 ID 或类别过滤?或者通过属性选择器[]?
    • 只需将e.tagName 替换为e.classNamee.id,例如:const byClass = [...elems].filter(e =&gt; {return e.className == 'class1'});
    • @RokoC.Buljan,定义。硬编码和替换是不可取的,但这只是给出一个想法,理想情况下,这将被调整并包装在一个带有参数的函数中以便更好地使用。
    猜你喜欢
    • 2021-11-12
    • 2017-08-26
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 2022-06-16
    • 1970-01-01
    相关资源
    最近更新 更多