【问题标题】:Check if an element contains a class in JavaScript?检查元素是否包含 JavaScript 中的类?
【发布时间】:2011-08-19 09:52:33
【问题描述】:

使用纯 JavaScript(不是 jQuery),有什么方法可以检查一个元素 是否包含一个类?

目前,我正在这样做:

var test = document.getElementById("test");
var testClass = test.className;

switch (testClass) {
  case "class1":
    test.innerHTML = "I have class1";
    break;
  case "class2":
    test.innerHTML = "I have class2";
    break;
  case "class3":
    test.innerHTML = "I have class3";
    break;
  case "class4":
    test.innerHTML = "I have class4";
    break;
  default:
    test.innerHTML = "";
}
<div id="test" class="class1"></div>

问题是,如果我将 HTML 更改为此...

<div id="test" class="class1 class5"></div>

...不再完全匹配,所以我得到的默认输出为空("")。但我仍然希望输出为I have class1,因为&lt;div&gt; 仍然包含 .class1 类。

【问题讨论】:

  • element.classList.contains(cls)
  • document.getElementsByClassName('class1').length

标签: javascript html css dom


【解决方案1】:

使用element.classList.contains方法:

element.classList.contains(class);

这适用于所有当前的浏览器,并且有 polyfills 也支持旧浏览器。


或者,如果您使用较旧的浏览器并且不想使用 polyfill 来修复它们,使用 indexOf 是正确的,但您必须稍微调整一下:

function hasClass(element, className) {
    return (' ' + element.className + ' ').indexOf(' ' + className+ ' ') > -1;
}

否则,如果您要查找的类是另一个类名的一部分,您还将获得 true

DEMO

jQuery 使用类似(如果不相同)的方法。


应用于示例:

由于这不能与 switch 语句一起使用,因此您可以使用以下代码达到相同的效果:

var test = document.getElementById("test"),
    classes = ['class1', 'class2', 'class3', 'class4'];

test.innerHTML = "";

for(var i = 0, j = classes.length; i < j; i++) {
    if(hasClass(test, classes[i])) {
        test.innerHTML = "I have " + classes[i];
        break;
    }
}

它也更少冗余;)

【讨论】:

  • 太棒了,但是如何将它与 switch 语句结合使用,以便我可以根据 div 包含的类来更改输出?
  • @daGUY:你想用 switch 语句做什么?例如。第二个div 有两个类,但它只会在您使用break 时输出I have class1。如果您想输出元素的每个类,那么您只需将className 拆分为空格即可。或者你的实际目标是什么?
  • 仅供参考:对于 svg 元素,在 safari 等浏览器中,className 不是字符串,而是 svganimatedstring 类型的对象。如果您正在使用 svg 元素,则检查类属性而不是类名是目前检查类的最跨浏览器的方法。
  • 您在前后添加空格是否有特定原因?
  • @KayceBasques:因为我们还在cls 中添加了空格,以便我们只匹配完整的类名。 hasClass(element, 'foo') 不应与 foobar 类匹配。如果我们不向element.className 添加空格,我们将永远无法匹配第一个或最后一个类名。
【解决方案2】:

简单有效的解决方案是尝试 .contains 方法。

test.classList.contains(testClass);

【讨论】:

  • contains 属性的element.classList 方法
  • 注意!并非所有浏览器都支持,更多信息在这里:caniuse.com/#feat=classlist
  • 这是一个很好的答案,我相信 .contains() 现在有更广泛的支持。
【解决方案3】:

在现代浏览器中,您可以只使用Element.classListcontains 方法:

testElement.classList.contains(className)

演示

var testElement = document.getElementById('test');

console.log({
    'main' : testElement.classList.contains('main'),
    'cont' : testElement.classList.contains('cont'),
    'content' : testElement.classList.contains('content'),
    'main-cont' : testElement.classList.contains('main-cont'),
    'main-content' : testElement.classList.contains('main-content')
});
&lt;div id="test" class="main main-content content"&gt;&lt;/div&gt;

支持的浏览器

(来自CanIUse.com


Polyfill

如果您想使用Element.classList,但又想支持旧版浏览器,请考虑使用this polyfill by Eli Grey

【讨论】:

    【解决方案4】:

    Element.matches()

    element.matches(selectorString)

    根据MDN Web Docs

    Element.matches() 方法返回true 如果元素将被指定的选择器字符串选择;否则,返回false

    因此,您可以使用Element.matches() 来确定元素是否包含类。

    const element = document.querySelector('#example');
    
    console.log(element.matches('.foo')); // true
    &lt;div id="example" class="foo bar"&gt;&lt;/div&gt;

    View Browser Compatibility

    【讨论】:

    • 对我来说似乎更干净且不那么麻烦,但我很好奇这在性能方面的比较。
    • @kasimir .matches 慢 3-4 倍。 jsben.ch/iKweE
    【解决方案5】:

    既然他想使用 switch(),我很惊讶还没有人提出这个:

    var test = document.getElementById("test");
    var testClasses = test.className.split(" ");
    test.innerHTML = "";
    for(var i=0; i<testClasses.length; i++) {
        switch(testClasses[i]) {
            case "class1": test.innerHTML += "I have class1<br/>"; break;
            case "class2": test.innerHTML += "I have class2<br/>"; break;
            case "class3": test.innerHTML += "I have class3<br/>"; break;
            case "class4": test.innerHTML += "I have class4<br/>"; break;
            default: test.innerHTML += "(unknown class:" + testClasses[i] + ")<br/>";
        }
    }
    

    【讨论】:

    • 我只是想知道同样的事情,但是是的,这是最接近原始问题的!
    【解决方案6】:

    这里有一个小 sn-p 如果你想检查元素是否包含一个类,而不使用 jQuery。

    function hasClass(element, className) {
        return element.className && new RegExp("(^|\\s)" + className + "(\\s|$)").test(element.className);
    }
    

    这说明元素可能包含多个由空格分隔的类名。


    您也可以将此函数分配给元素原型。

    Element.prototype.hasClass = function(className) {
        return this.className && new RegExp("(^|\\s)" + className + "(\\s|$)").test(this.className);
    };
    

    并像这样触发(很像jQuery的.hasClass()函数):

    document.getElementById('MyDiv').hasClass('active');
    

    【讨论】:

    • 我更喜欢这个解决方案。它避免了类名部分匹配另一个类的问题,并且不需要 polyfills 在 IE 中工作。
    【解决方案7】:

    这有点旧,但也许有人会发现我的解决方案有帮助:

    // Fix IE's indexOf Array
    if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (searchElement) {
            if (this == null) throw new TypeError();
            var t = Object(this);
            var len = t.length >>> 0;
            if (len === 0) return -1;
            var n = 0;
            if (arguments.length > 0) {
                n = Number(arguments[1]);
                if (n != n) n = 0;
                else if (n != 0 && n != Infinity && n != -Infinity) n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
            if (n >= len) return -1;
            var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
            for (; k < len; k++) if (k in t && t[k] === searchElement) return k;
            return -1;
        }
    }
    // add hasClass support
    if (!Element.prototype.hasClass) {
        Element.prototype.hasClass = function (classname) {
            if (this == null) throw new TypeError();
            return this.className.split(' ').indexOf(classname) === -1 ? false : true;
        }
    }
    

    【讨论】:

    • 使用:'element.hasClass('classname');
    • 你为什么使用 t.length >>> 0 ?据我所知,如果你使用 '0' 就不会了,对吧?
    • 哇,这么多简单的代码。为什么不使用正则表达式而不是重新发明轮子?你可以只使用 /^class_name_you_are_searching_for$/.test(myElement.className)
    • 我写得太快了。只是为了不使我的正则表达式过于复杂,它将是 /\s*class_name_you_are_searching_for\s*/.test(myElement.className)
    • @pqsk - 我编写自己的库以备将来使用。这只是增加了我的堆栈。当然其他解决方案也可以,这只是我的首选方式
    【解决方案8】:

    className 只是一个字符串,因此您可以使用常规的indexOf 函数来查看类列表是否包含另一个字符串。

    【讨论】:

    • 在上面的例子中测试class类怎么样?
    • 根据经验,这种方法风险很大:当您在具有foobar 类的元素上查找foo 类时,它将返回true。
    • 当然,您只需了解您正在测试的内容。 Felix 的代码使用空格作为分隔符,效果很好。
    • 未能考虑类名的嵌套实例。示例:“end”可以在类名“frontend”中找到。
    【解决方案9】:

    简化的单线:1

    function hasClassName(classname,id) {
     return  String ( ( document.getElementById(id)||{} ) .className )
             .split(/\s/)
             .indexOf(classname) >= 0;
    }
    

    1indexOf IE 不支持数组(当然)。在网上可以找到很多猴子补丁。

    【讨论】:

    • 单词边界的问题是类名的一些有效字符,例如-,被认为是单词边界。例如。寻找foo 并且类是foo-bar 产生true
    • 你是对的。删除了原来的,添加了另一种方法。仍然是单线器。
    【解决方案10】:

    我知道有很多答案,但其中大部分是针对附加功能和附加类的。这是我个人使用的;更简洁,代码行更少!

    if( document.body.className.match('category-page') ) { 
      console.log('yes');
    }
    

    【讨论】:

    • 此方法在搜索部分匹配的类名称时可能会返回误报 - 例如&lt;body class="category-page"&gt;document.body.className.match('page') - 将匹配但没有附加到元素的类 page
    • 可以用\b解决,例如/\bpage\b/g,因为它是正则表达式(注意:必须使用/ /g)。
    【解决方案11】:

    我已经创建了一个原型方法,它使用classList,如果可能的话,使用indexOf

    Element.prototype.hasClass = Element.prototype.hasClass || 
      function(classArr){
        var hasClass = 0,
            className = this.getAttribute('class');
      
        if( this == null || !classArr || !className ) return false;
      
        if( !(classArr instanceof Array) )
          classArr = classArr.split(' ');
    
        for( var i in classArr )
          // this.classList.contains(classArr[i]) // for modern browsers
          if( className.split(classArr[i]).length > 1 )  
              hasClass++;
    
        return hasClass == classArr.length;
    };
    
    
    ///////////////////////////////
    // TESTS (see browser's console when inspecting the output)
    
    var elm1 = document.querySelector('p');
    var elm2 = document.querySelector('b');
    var elm3 = elm1.firstChild; // textNode
    var elm4 = document.querySelector('text'); // SVG text
    
    console.log( elm1, ' has class "a": ', elm1.hasClass('a') );
    console.log( elm1, ' has class "b": ', elm1.hasClass('b') );
    console.log( elm1, ' has class "c": ', elm1.hasClass('c') );
    console.log( elm1, ' has class "d": ', elm1.hasClass('d') );
    console.log( elm1, ' has class "a c": ', elm1.hasClass('a c') );
    console.log( elm1, ' has class "a d": ', elm1.hasClass('a d') );
    console.log( elm1, ' has class "": ', elm1.hasClass('') );
    
    console.log( elm2, ' has class "a": ', elm2.hasClass('a') );
    
    // console.log( elm3, ' has class "a": ', elm3.hasClass('a') );
    
    console.log( elm4, ' has class "a": ', elm4.hasClass('a') );
    <p class='a b c'>This is a <b>test</b> string</p>
    <svg xmlns="http://www.w3.org/2000/svg" width="100px" height="50px">
        <text x="10" y="20" class='a'>SVG Text Example</text>
    </svg>

    Test page

    【讨论】:

    • 您是否有理由要使用类列表而不是 e.className 的索引?似乎性能不太好
    • @Ced - 好吧,如果您不为他们的类测试数千个元素,那么性能是无关紧要的(将来可能会在浏览器中重构)。使用起来更优雅,因为代码描述了它的功能,但归根结底,没关系,随心所欲:)
    【解决方案12】:

    要检查一个元素是否包含一个类,可以使用该元素的 classList 属性的 contains() 方法:*

    element.classList.contains(className);
    

    *假设你有以下元素:

    <div class="secondary info">Item</div>*
    

    要检查元素是否包含二级类,请使用以下代码:

     const div = document.querySelector('div');
     div.classList.contains('secondary'); // true
    

    以下返回 false 因为元素没有类错误:

     const div = document.querySelector('div');
     div.classList.contains('error'); // false
    

    【讨论】:

      【解决方案13】:

      element.classList.contains() 对这个问题的回答非常中肯,但人们的回答相当夸张,并提出了一些大胆的主张,so I ran a benchmark

      请记住,每个测试都进行 1000 次迭代,因此其中大部分仍然非常快。除非您在特定操作中广泛依赖它,否则您不会看到性能差异。

      我基本上用各种方法进行了一些测试。在我的机器上(Win 10、24gb、i7-8700),classList.contains 表现非常好。 className.split(' ') 也是如此,实际上是相同的。

      虽然获胜者是classList.contains()。如果您不检查 classList 是否为 undefined~(' ' + v.className + ' ').indexOf(' c' + i + ' ') 会提前 5-15%

      【讨论】:

        【解决方案14】:

        这是一个不区分大小写的简单解决方案:

        function hasClass(element, classNameToTestFor) {
            var classNames = element.className.split(' ');
            for (var i = 0; i < classNames.length; i++) {
                if (classNames[i].toLowerCase() == classNameToTestFor.toLowerCase()) {
                    return true;
                }
            }
            return false;
        }
        

        【讨论】:

          【解决方案15】:
          1. Felix 在 className 和您要搜索的字符串的两侧添加空格的技巧是确定元素是否具有类的正确方法。

          2. 要根据类有不同的行为,您可以在映射中使用函数引用或函数:

            function fn1(element){ /* code for element with class1 */ }
            
            function fn2(element){ /* code for element with class2 */ }
            
            function fn2(element){ /* code for element with class3 */ }
            
            var fns={'class1': fn1, 'class2': fn2, 'class3': fn3};
            
            for(var i in fns) {
                if(hasClass(test, i)) {
                    fns[i](test);
                }
            }
            
            • for(var i in fns) 遍历 fns 映射中的键。
            • 在 fnsi 之后没有中断允许在匹配时执行代码 - 这样,如果元素具有 f.i.、class1 和 class2,则 fn1 和 fn2 都将被执行。
            • 这种方法的优点是为每个类执行的代码是任意的,就像 switch 语句中的代码一样;在您的示例中,所有案例都执行了类似的操作,但明天您可能需要为每个案例做不同的事情。
            • 您可以通过一个状态变量来模拟默认情况,告诉您是否在循环中找到匹配项。

          【讨论】:

            【解决方案16】:

            如果元素只有一个类名,您可以通过获取类属性快速检查它。其他答案要可靠得多,但这肯定有它的用例。

            if ( element.getAttribute('class') === 'classname' ) {
            
            }
            

            【讨论】:

              【解决方案17】:

              IE8+ 支持此功能。

              首先我们检查classList是否存在,如果存在我们可以使用IE10+支持的contains方法。如果我们在 IE9 或 8 上,它会回退到使用正则表达式,虽然效率不高,但它是一个简洁的 polyfill。

              if (el.classList) {
                el.classList.contains(className);
              } else {
                new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
              }
              

              或者,如果您使用 babel 进行编译,您可以简单地使用: el.classList.contains(className);

              【讨论】:

                【解决方案18】:

                我将 Poly 填充 classList 功能并使用新语法。这样,较新的浏览器将使用新的实现(速度更快),并且只有旧浏览器会受到代码的性能影响。

                https://github.com/remy/polyfills/blob/master/classList.js

                【讨论】:

                  【解决方案19】:

                  这有点不对劲,但是如果你有触发 switch 的事件,你可以不用类:

                  <div id="classOne1"></div>
                  <div id="classOne2"></div>
                  <div id="classTwo3"></div>
                  

                  你可以的

                  $('body').click( function() {
                  
                      switch ( this.id.replace(/[0-9]/g, '') ) {
                          case 'classOne': this.innerHTML = "I have classOne"; break;
                          case 'classTwo': this.innerHTML = "I have classTwo"; break;
                          default: this.innerHTML = "";
                      }
                  
                  });
                  

                  .replace(/[0-9]/g, '')id 中删除数字。

                  这有点hacky,但适用于没有额外功能或循环的长开关

                  【讨论】:

                    【解决方案20】:

                    查看此 Codepen 链接,以更快、更轻松地检查元素是否具有使用原生 JavaScript 的特定类~!

                    hasClass (Vanilla JS)

                    function hasClass(element, cls) {
                        return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1;
                    }
                    

                    【讨论】:

                      【解决方案21】:

                      使用classList也很理想

                      HTML

                      <div id="box" class="myClass"></div>
                      

                      JavaScript

                      const element = document.querySelector("#box");
                      
                      element.classList.contains("myClass");
                      

                      【讨论】:

                        【解决方案22】:

                        正如公认的答案所暗示的,Element.className 返回一个字符串,因此您可以使用indexOf() 方法轻松检查一个类是否存在:

                        element.className.indexOf('animated') > -1
                        

                        如果您对indexOfclassList.contains 之间的性能差异感兴趣,使用indexOf 似乎会稍快一些。我做了一个快速的基准性能测试来检查这一点。以下是我的发现:ClassName.indexOf vs ClassList.contains

                        【讨论】:

                          【解决方案23】:

                          试试这个:

                          document.getElementsByClassName = function(cl) {
                             var retnode = [];
                             var myclass = new RegExp('\\b'+cl+'\\b');
                             var elem = this.getElementsByTagName('*');
                             for (var i = 0; i < elem.length; i++) {
                                 var classes = elem[i].className;
                                 if (myclass.test(classes)) retnode.push(elem[i]);
                             }
                              return retnode;
                          };
                          

                          【讨论】:

                          • 注意单词边界。如果您有例如,它也将匹配 true一个类foo-bar 并搜索foo
                          • 嗨 Jimy,所以我正在搜索这个 \b metacharacter,它只将 [a-zA-Z0-9_] 视为单词字符。因此,对于包含减号字符 this won't workclassnames
                          【解决方案24】:

                          我认为完美的解决方案是这样的

                          if ($(this).hasClass("your_Class")) 
                              alert("positive");            
                          else              
                              alert("Negative");
                          

                          【讨论】:

                          • 1. “使用纯 JavaScript(不是 jQuery)” 2. 使用括号
                          • 3 - 使用括号
                          【解决方案25】:

                          当前在哪个元素中是类 '.bar' ?这是另一种解决方案,但取决于您。

                          var reg = /Image/g, // regexp for an image element
                          query = document.querySelector('.bar'); // returns [object HTMLImageElement]
                          query += this.toString(); // turns object into a string
                          
                          if (query.match(reg)) { // checks if it matches
                            alert('the class .bar is attached to the following Element:\n' + query);
                          }
                          

                          jsfiddle demo

                          当然,这只是对 1 个简单元素 &lt;img&gt;(/Image/g) 的查找,但您可以将所有元素放在一个数组中,例如 &lt;li&gt;/LI/g&lt;ul&gt; = /UL/g 等。

                          【讨论】:

                            【解决方案26】:

                            只是为那些试图在内联 SVG 元素中查找类名的人添加答案。

                            hasCLass() 函数更改为:

                            function hasClass(element, cls) {
                                return (' ' + element.getAttribute('class') + ' ').indexOf(' ' + cls + ' ') > -1;
                              }
                            

                            您需要使用getAttribute() 方法来获取类名,而不是使用className 属性。

                            【讨论】:

                              【解决方案27】:

                              我为我的网站创建了这些功能,我只使用 vanilla javascript,也许它会对某人有所帮助。 首先,我创建了一个函数来获取任何 HTML 元素:

                              //return an HTML element by ID, class or tag name
                                  var getElement = function(selector) {
                                      var elements = [];
                                      if(selector[0] == '#') {
                                          elements.push(document.getElementById(selector.substring(1, selector.length)));
                                      } else if(selector[0] == '.') {
                                          elements = document.getElementsByClassName(selector.substring(1, selector.length));
                                      } else {
                                          elements = document.getElementsByTagName(selector);
                                      }
                                      return elements;
                                  }
                              

                              然后是接收要删除的类的函数和元素的选择器:

                              var hasClass = function(selector, _class) {
                                      var elements = getElement(selector);
                                      var contains = false;
                                      for (let index = 0; index < elements.length; index++) {
                                          const curElement = elements[index];
                                          if(curElement.classList.contains(_class)) {
                                              contains = true;
                                              break;
                                          }
                                      }
                                      return contains;
                                  }
                              

                              现在你可以像这样使用它了:

                              hasClass('body', 'gray')
                              hasClass('#like', 'green')
                              hasClass('.button', 'active')
                              

                              希望它会有所帮助。

                              【讨论】:

                                【解决方案28】:

                                提示:尽量在你的项目中移除 jQuery 的依赖 - VanillaJS

                                document.firstElementChild 返回&lt;html&gt; 标记,然后classList 属性返回所有添加到它的类。

                                if(document.firstElementChild.classList.contains("your-class")){
                                    // <html> has 'your-class'
                                } else {
                                    // <html> doesn't have 'your-class'
                                }
                                

                                【讨论】:

                                  【解决方案29】:

                                  由于.className是一个字符串,你可以使用字符串includes()方法来检查你的.className是否包含你的类名:

                                  element.className.includes("class1")
                                  

                                  【讨论】:

                                    【解决方案30】:

                                    对我来说,最优雅、最快捷的实现方式是:

                                    function hasClass(el, cl) {
                                            return el.classList ? el.classList.contains(cl) : !!el.className && !!el.className.match(new RegExp('(?: |^)' + cl + '(?: |$)'));
                                        }
                                    

                                    【讨论】:

                                    • 首先,正则表达式并不完全可靠或高效。 (捕获组)是不必要的。你应该使用(?: |^)c'+i+'(?: |$). 其次,这远不是最快的。 jsben.ch/QAOQs
                                    • @RegularJo 我运行了你的测试,但结果是正则表达式是最快的
                                    • @RegularJo 你的正则表达式中的“c”也是错误的,正确的正则表达式是 '(?: |^)'+i+'(?: |$)'
                                    • 大声笑,是的,忘记从测试中更新我的正则表达式以将 c 改回来。
                                    猜你喜欢
                                    • 2021-05-24
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2016-05-24
                                    • 2016-10-13
                                    • 2013-07-31
                                    相关资源
                                    最近更新 更多