可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Using plain JavaScript (not jQuery), is there a way I can test to see if an element contains a class?
Currently, I\'m doing this:
HTML:
<div id=\"test\" class=\"class1\"></div>;
JS:
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 = \"\";
}
This results in this output, which is correct:
I have class1
The issue is that if I change the HTML to this...
<div id=\"test\" class=\"class1 class5\"></div>
...there\'s no longer an exact match, so I get the default output of nothing (\"\"
). But I still want the output to be I have class1
because the <div>
still contains the .class1
class.
回答1:
Use element.classList
.contains
method:
element.classList.contains(class);
This works on all current browsers and there are polyfills to support older browsers too.
Alternatively, if you work with older browsers and don\'t want to use polyfills to fix them, using indexOf
is correct, but you have to tweak it a little:
function hasClass(element, className) {
return (\' \' + element.className + \' \').indexOf(\' \' + className+ \' \') > -1;
}
Otherwise you will also get true
if the class you are looking for is part of another class name.
DEMO
jQuery uses a similar (if not the same) method.
Applied to the example:
As this does not work together with the switch statement, you could achieve the same effect with this code:
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;
}
}
It\'s also less redundant ;)
回答2:
The easy and effective solution is trying .contains method.
test.classList.contains(testClass);
回答3:
In modern browsers, you can just use the contains
method of Element.classList
:
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\')
});
<div id=\"test\" class=\"main main-content content\"></div>
Supported browsers
(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.
回答4:
Since he wants to use switch(), I\'m surprised no one has put this forth yet:
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/>\";
}
}
回答5:
A simplified oneliner:1
function hasClassName(classname,id) {
return String ( ( document.getElementById(id)||{} ) .className )
.split(/\\s/)
.indexOf(classname) >= 0;
}
1 indexOf
for arrays is not supported by IE (ofcourse). There are plenty of monkey patches to be found on the net for that.
回答6:
This is a little old, but maybe someone will find my solution helpfull:
// 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;
}
}
回答7:
Here is a little snippet If you’re trying to check wether element contains a class, without using jQuery.
function hasClass(element, className) {
return element.className && new RegExp(\"(^|\\\\s)\" + className + \"(\\\\s|$)\").test(element.className);
}
This accounts for the fact that element might contain multiple class names separated by space.
OR
You can also assign this function to element prototype.
Element.prototype.hasClass = function(className) {
return this.className && new RegExp(\"(^|\\\\s)\" + className + \"(\\\\s|$)\").test(this.className);
};
And trigger it like this (very similar to jQuery’s .hasClass()
function):
document.getElementById(\'MyDiv\').hasClass(\'active\');
回答8:
className
is just a string so you can use the regular indexOf function to see if the list of classes contains another string.
回答9:
I know there a lot of answers but most of these are for additional functions and additional classes. This is the one I personally use; much cleaner and much less lines of code!
if( document.body.className.match(\'category-page\') ) {
console.log(\'yes\');
}
回答10:
Here\'s a case-insensitive trivial solution:
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;
}
回答11:
I\'ve created a prototype method which uses classList
, if possible, else resorts to 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
回答12:
Felix\'s trick of adding spaces to flank the className and the string you\'re searching for is the right approach to determining whether the elements has the class or not.
To have different behaviour according to the class, you may use function references, or functions, within a 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(var i in fns) iterates through the keys within the fns map.
- Having no break after fnsi allows the code to be executed whenever there is a match - so that if the element has, f.i., class1 and class2, both fn1 and fn2 will be executed.
- The advantage of this approach is that the code to execute for each class is arbitrary, like the one in the switch statement; in your example all the cases performed a similar operation, but tomorrow you may need to do different things for each.
- You may simulate the default case by having a status variable telling whether a match was found in the loop or not.
回答13:
I would Poly fill the classList functionality and use the new syntax. This way newer browser will use the new implementation (which is much faster) and only old browsers will take the performance hit from the code.
https://github.com/remy/polyfills/blob/master/classList.js
回答14:
If the element only has one class name you can quickly check it by getting the class attribute. The other answers are much more robust but this certainly has it\'s use cases.
if ( element.getAttribute(\'class\') === \'classname\' ) {
}
回答15:
Try this one:
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;
};
回答16:
I think that perfect solution will be this
if ($(this).hasClass(\"your_Class\"))
alert(\"positive\");
else
alert(\"Negative\");
回答17:
in which element is currently the class \'.bar\' ? Here is another solution but it\'s up to you.
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
Of course this is only a lookup for 1 simple element <img>
(/Image/g
) but you can put all in an array like <li>
is /LI/g
, <ul>
= /UL/g
etc.
回答18:
This is a bit off, but if you have an event that triggers switch, you can do without classes:
<div id=\"classOne1\"></div>
<div id=\"classOne2\"></div>
<div id=\"classTwo3\"></div>
You can do
$(\'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, \'\')
removes digits from id
.
It is a bit hacky, but works for long switches without extra functions or loops
回答19:
See this Codepen link for faster and easy way of checking an element if it has a specific class using vanilla JavaScript~!
hasClass (Vanilla JS)
function hasClass(element, cls) {
return (\' \' + element.className + \' \').indexOf(\' \' + cls + \' \') > -1;
}
回答20:
This is supported on IE8+.
First we check if classList
exists if it does we can use the contains
method which is supported by IE10+. If we are on IE9 or 8 it falls back to using a regex, which is not as efficient but is a concise polyfill.
if (el.classList)
el.classList.contains(className);
else
new RegExp(\'(^| )\' + className + \'( |$)\', \'gi\').test(el.className);
回答21:
Just to add to the answer for people trying to find class names within inline SVG elements.
Change the hasCLass()
function to:
function hasClass(element, cls) {
return (\' \' + element.getAttribute(\'class\') + \' \').indexOf(\' \' + cls + \' \') > -1;
}
Instead of using the className
property you\'ll need to use the getAttribute()
method to grab the class name.
回答22:
Element.matches()
element.matches(selectorString)
According to MDN Web Docs:
The Element.matches()
method returns true
if the element would be selected by the specified selector string; otherwise, returns false
.
Therefore, you can use Element.matches()
to determine if an element contains a class.
const element = document.querySelector(\'#example\');
console.log(element.matches(\'.foo\')); // true
<div id=\"example\" class=\"foo bar\"></div>
View Browser Compatibility
回答23:
For me the most elegant and faster way to achieve it is:
function hasClass(el,cl){
return !!el.className && !!el.className.match(new RegExp(\'\\\\b(\'+cl+\')\\\\b\'));
}