检查一个元素是否包含JavaScript中的类?

使用纯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>

The issue is that if I change the HTML to this...

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

…不再有完全匹配,所以我得到的默认输出为无("")。但我仍然希望输出为I have class1,因为<div>仍然是包含.class1类。

1287337 次浏览

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

使用element.classList.contains方法:

element.classList.contains(class);

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


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

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

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

演示

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;}}

它也更少冗余;)

试试这个:

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;};

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

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;}

一个简化的oneliner:1

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

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

  1. Felix的技巧是在class Name和要搜索的字符串旁边添加空格,这是确定元素是否具有类的正确方法。

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

    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(fns中的var i)遍历fns映射中的键。
    • 在fnsi之后没有中断允许在有匹配时执行代码-因此,如果元素具有f. i.、类1和类2,则将同时执行fn1和fn2。
    • 这种方法的优点是,为每个类执行的代码是任意的,就像Switch语句中的代码一样;在您的示例中,所有情况都执行了类似的操作,但明天您可能需要为每个情况执行不同的操作。
    • 您可以通过让状态变量告诉是否在循环中找到匹配来模拟默认情况。

因为他想使用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/>";}}

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

// Fix IE's indexOf Arrayif (!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 supportif (!Element.prototype.hasClass) {Element.prototype.hasClass = function (classname) {if (this == null) throw new TypeError();return this.className.split(' ').indexOf(classname) === -1 ? false : true;}}

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

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

我将Poly填充类列表功能并使用新的语法。这样新的浏览器将使用新的实现(速度要快得多),只有旧的浏览器才会受到代码性能的影响。

我创建了一个使用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 browsersif( 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; // textNodevar 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>

测试页

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

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

这是一个小片段,如果你试图在不使用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');

简单而有效的解决方案是尝试.包含方法。

test.classList.contains(testClass);

我知道有很多答案,但大多数都是针对附加函数和附加类的。这是我个人使用的;更干净,代码行更少!

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

在现代浏览器中,您可以只使用#1contains方法:

testElement.classList.contains(className)

Demo

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'),'main main-content' : testElement.classList.contains('main main-content')});
<div id="test" class="main main-content content"></div>


Supported browsers

enter image description here

(from CanIUse.com)


Polyfill

If you want to use Element.classList but you also want to support older browsers, consider using this polyfill by Eli Grey.

哪个元素当前是类“. bar”?这里有另一个解决方案,但这取决于你。

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

jsfiddle demo

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

这有点偏离,但如果你有一个触发开关的事件,你可以不使用类:

<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中删除数字。

它有点老土,但适用于没有额外功能或循环的长开关

请参阅此CoDepen链接,以更快、更简单地检查元素是否具有使用vanilla JavaScript的特定类~!

hasClass(香草JS)

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

对我来说,最优雅、最快捷的方法是:

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

输入图片描述

这在IE8+上是支持的。

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

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

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

只是为了增加人们试图在内联SVG元素中查找类名的答案。

hasCLass()函数更改为:

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

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

Element.matches()

element.matches选择器

根据MDN Web文档

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

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

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

View Browser Compatibility

我为我的网站创建了这些功能,我只使用香草JavaScript,也许它会帮助某人。首先,我创建了一个函数来获取任何超文本标记语言元素:

//return an HTML element by ID, class or tag namevar 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')

希望能有所帮助。

提示:尝试尽可能多地删除项目中jQuery的依赖项-香草

document.firstElementChild返回<html>标签,然后classList属性返回添加到它的所有类。

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

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

element.className.includes("class1")

使用类列表也是理想的

超文本标记语言

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

javascript

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

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

element.classList.contains(className);

*假设您有以下元素:

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

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

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

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

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

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

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

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

这个问题得到了element.classList.contains()的可靠回答,但是人们对他们的答案非常奢侈,并提出了一些大胆的主张,所以我做了个测试

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

我用各种方法做了一些测试。在我的机器上,(Win 10,24GB, i7-8700),classList.contains表现非常好。className.split也是如此 (' ') 实际上是一样的。

获胜者是classList.contains()。如果你不检查类列表是否为undefined~(' ' + v.className + ' ').indexOf(' ' + classToFind + ' ')会领先5-15%

在此处输入图片描述