【问题标题】:plain js to select element by attribute name starts with纯js按属性名称选择元素以
【发布时间】:2017-01-16 02:13:19
【问题描述】:

上下文:

  • HTML

     <div ng-me=""></div>
     <div ng-you=""></div>
      <p ng-you=""></p>
    

我想选择所有属性名称以ng-开头的元素。


使用 jQuery,以下链接是最接近此问题的线程:

  1. jQuery - How to select value by attribute name starts with.

  2. How to remove all Attributes by attribute name starts with.

然而,第一个使用 jQuery,第二个解决了 removing 已经选择的元素 NOT selection 的问题。

我试试这个:

document.querySelectorAll('[ng-*]')

它不起作用,而是抛出错误。

【问题讨论】:

    标签: javascript regex selector built-in


    【解决方案1】:

    这里我使用 querySelectorAll 来获取我想要检查的所有对象。

    那我看看每个返回对象的属性集合

    ES6+

    const attrStartsWith = (sel,str) => [...document.querySelectorAll(sel)]
      .filter(ele => [...ele.attributes]
        .filter(({name}) => name.startsWith(str))
        .length>0
      )
    
    console.log(attrStartsWith("*","ng")); // all
    console.log(attrStartsWith("div","ng")); // divs
    <div ng-a="a">a</div>
    <div ng-b="b">b</div>
    <p ng-c="c">c</p>

    ES5 及以下

    function attrStartsWith(sel,str) {
      var el = document.querySelectorAll(sel), res=[];
      
      for (var i = 0, n=el.length; i < n; i++){
        for (var j=0;j<el[i].attributes.length;j++) {
          if (el[i].attributes[j].name.indexOf(str)==0) {
            res.push(el[i]); 
          }
        }
      }
      return res;
    }
    console.log(attrStartsWith("*","ng")); // all
    console.log(attrStartsWith("div","ng")); // divs
    <div ng-a="a">a</div>
    <div ng-b="b">b</div>
    <p ng-c="c">c</p>

    【讨论】:

    • 如果我们的标签是p、a .. 除了div 之外的任何标签。超动力的东西
    • 哦..我现在得到了你的分析器..你似乎在编辑它..这就是为什么我把我的答案最接近你的答案编辑..因此,你应该得到
    • 我在 3 小时前将代码更改为函数以回复您的问题 :)
    • 嗨@mplungjan,我真的有同样的问题:谁投反对票?为什么?
    【解决方案2】:

    ES6 解决方案:

    const attrStartsWith = (prefix) =>
      Array.from(document.querySelectorAll('*'))
       .filter(
          (e) => Array.from(e.attributes).filter(
            ({name, value}) => name.startsWith(prefix)).length
       )
    

    然后:

    attrStartsWith('ng-') // return an array of HTML elements which  have attributes name starts with "ng-"
    

    2017-12-02 的版本

    const queryByAttrNameStartsWith = (contextualSelector = '*') => {
      const elements = Array.from(document.querySelectorAll(contextualSelector));
      return (prefix) =>
        elements.filter(e =>
          Array.from(e.attributes).find(({ name, value }) =>
            name.startsWith(prefix)
          )
        );
    };
    //then
    queryByAttrNameStartsWith('*')('data-'); // all elements that have attribute name that starts with 'data-'
    queryByAttrNameStartsWith('div')('ng-'); // ony DIV elements that have attribute name that starts with 'ng-'
    //.. so on
    

    或:

    NodeList.prototype.filterByAttrNameStartsWith = function(prefix) {
      return Array.from(this).filter(e =>
        Array.from(e.attributes).find(({ name, value }) => name.startsWith(prefix))
      );
    };
    //then
    document.querySelectorAll('*')
     .filterByAttrNameStartsWith('data-'); // all elements that have attribute name that starts with 'data-'
    document.querySelectorAll('div')
     .filterByAttrNameStartsWith('ng-'); // ony DIV elements that have attribute name that starts with 'ng-'
    //.. so on
    

    【讨论】:

    • 是的!但它是这个问题的非功能性要求,只是它让生活变得简单(易于阅读代码,易于维护,......等等)
    • 相当优雅的版本
    【解决方案3】:

    死灵术。

    ES 5 解决方案:

        function findElementsWithArributePrefix(selector, prefix)
        {
            return [].slice.call(document.querySelectorAll(selector)).filter(function (e)
            {
                return [].slice.call(e.attributes).filter(
                    function (attr)
                    {
                        return attr.name.startsWith(prefix);
                    }
                ).length;
            });
        }
    

    然后:

    console.log("prfx", findElementsWithArributePrefix("*", "ng-"));
    

    【讨论】:

    • @mplungjan:不,如果你有,那是别人。
    【解决方案4】:

    所以我将 gavgrif 和 mplungjan 的努力与我已经完成的工作结合起来:

    HTML:

     <div ng-me="">1</div>
     <div ng-you="">2</div>
     <div not-me="">3</div>
     <div ng-yes="">4</div>
    

    CSS:

    .ng-class {
        background-color: red;
    }
    

    JavaScript:

    var el = document.getElementsByTagName("*");
    var list = [];
    
    // Grab all elements on the page and check them for attributes
    for (var i = 0, n = el.length; i < n; i++) {
         for (var j = 0; j < el[i].attributes.length; j++) {
            // If match, push into seperate array
            if (el[i].attributes[j].name.indexOf("ng") == 0)       
                list.push(el[i]);
         }
    }
    
    // Add a custom class to these elements
    for(var i = 0; i < list.length; i++) {
        list[i].classList.add('ng-class');
    }
    

    Codepen example here

    【讨论】:

    • 你现在的解决方案确实比我的好,尤其是在编辑之后。 (也更清洁)。 fwiw:我投了赞成票,并从中吸取了教训。
    【解决方案5】:

    div [^="ng-"] 应该为你做这件事 - 这样做是明确所有具有以“ng-”开头的属性的元素(并且在他的示例中应用背景颜色)

    *[^="ng-"] {background-color:red}
    

    【讨论】:

    • * [^="ng-"] 选择器不是更好吗?不知道OP除了&lt;div&gt;还有没有其他元素
    • 另外,这不起作用,因为它不针对属性的名称,只针对值。
    • 正如@Roberrrt 所说-我不正确-这仅针对属性的值-而不是名称。我发布了它 - 以为我很聪明,然后实际上阅读了基于属性的选择器并意识到我不是很聪明。我会留下这个帖子,因为它对 OP 有帮助,并且它可能允许其他人开始考虑基于属性内容的特定选择器。谢谢
    • 这是document.querySelectorAll不接受的css选择器
    猜你喜欢
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 2020-11-03
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多