Перевірте, чи містить елемент клас у JavaScript?


585

Використовуючи звичайний 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тому що <div>все ще містить в .class1клас.


5
element.classList.contains (cls)
Ронні Ройстон

Відповіді:


1034

Метод використання :element.classList .contains

element.classList.contains(class);

Це працює на всіх поточних веб-переглядачах, і є поліфіли для підтримки старих браузерів.


Крім того , якщо ви працюєте зі старими веб-переглядачами і не хочете використовувати поліфіли для їх виправлення, використовуючи 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;
    }
}

Це також менш зайве;)


Дивовижно, але як я можу це використовувати в поєднанні з оператором переключення, щоб я міг змінити вихід, на основі яких класів містить div?
daGUY

@daGUY: Що ви хочете зробити з оператором переключення? Наприклад, у другому divє два класи, але він виводиться лише тоді, I have class1коли ви користуєтесь break. Якщо ви хочете вивести кожен клас, який має елемент, то ви можете просто взяти classNameта розділити його на пробіли. Або яка ваша реальна мета?
Фелікс Клінг

@Felix Kling: Мені потрібен внутрішній HTML-код div, щоб перейти між чотирма різними рядками залежно від того, який клас він містить. Я просто використав "я маю class1" і т.д. в якості прикладів - справжні рядки всі різні. Я показуватиму лише по одному рядку за раз, не поєднуючи жодного (звідси перерви після кожного випадку). Я просто хочу, щоб він все ще працював, навіть якщо клас, що відповідає, є одним із декількох класів на діві.
daGUY

@Felix Kling: це зробили, спасибі! Я фактично не вивожу імена класів, а скоріше один із чотирьох абсолютно різних рядків, тому я трохи змінив його за допомогою декількох операторів IF / ELSE IF для обробки кожного. Хоча працює чудово.
daGUY

1
Чи є конкретна причина, чому ви додавали пробіли до і після?
Ced

93

Просте і ефективне рішення намагається .Contains метод.

test.classList.contains(testClass);

3
containsметод в element.classListнерухомості
user907860

7
NB! Не підтримується у всіх браузерах, більше інформації тут: caniuse.com/#feat=classlist
Silver Ringvee

4
Це чудова відповідь, і я вважаю, що .contains () має набагато ширшу підтримку.
Ніколас Крейдберг

49

У сучасних браузерах ви можете просто використовувати containsметод Element.classList:

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')
});
<div id="test" class="main main-content content"></div>


Підтримувані веб-переглядачі

введіть тут опис зображення

(від CanIUse.com )


Поліфіл

Якщо ви хочете використовувати , Element.classListале ви також хочете , щоб підтримувати старі браузери, розглянути питання про використання цього polyfill від Елі Грей .


10

Оскільки він хоче використовувати перемикач (), я здивований, що цього ще ніхто не висунув:

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

1
Мені було просто цікаво те саме, але так, це найближче до початкової проблеми!
Silver Silvervee

8

Element.matches ()

element.matches (selectorString)

Згідно з веб-документами MDN :

У Element.matches()методі повертає , trueякщо елемент буде обраний зазначеної рядком селектора; інакше повертається false.

Тому ви можете використовувати, Element.matches()щоб визначити, чи містить елемент клас.

const element = document.querySelector('#example');

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

Перегляньте сумісність браузера


7

Ось невеликий фрагмент Якщо ви намагаєтеся перевірити, чи вміщений елемент містить клас, не використовуючи 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);
};

І запустити його так (дуже схоже на .hasClass()функцію jQuery ):

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

Я більше віддаю перевагу цьому рішенню. Це дозволяє уникнути випуску імені класу, що частково відповідає іншому класу, і не вимагає полізаповнення для роботи в IE.
scoota269

5

Спрощена лінійка: 1

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

1 indexOf для масивів IE не підтримується (звичайно). Для цього можна знайти безліч патчів мавп.


1
Проблема меж слова полягає в тому, що деякі дійсні символи для назв класів, такі як -, вважаються межами слова. Наприклад, шукаємо fooі клас - це foo-barврожайність true.
Фелікс Клінг

Ти правий. Вилучили оригінал, додали ще один підхід. Все-таки oneliner.
KooiInc

5

Це трохи старе, але, можливо, хтось знайде моє рішення корисним:

// 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 (' ім'я класу ');
Дементік

Чому ви використовували t.length >>> 0? Наскільки я знаю, це noop, якщо ви використовуєте "0", правда?
Vitor Canova

Ух так багато коду для чогось простого. Чому б не використовувати регулярний вираз і не винаходити колесо? ви можете просто використовувати /^class_name_you_are_searching_for$/.test(myElement.className)
pqsk

1
Я написав це занадто швидко. Тільки, щоб не ускладнювати моє регулярне вираження, було б /\s*class_name_you_are_searching_for\s*/.test(myElement.className)
pqsk

@pqsk - я пишу власні бібліотеки для подальшого використання. і це просто додає до моєї стеки. звичайно, інші рішення спрацювали б, це лише мій переважний спосіб
Демментик

4

classNameце лише рядок, тому ви можете використовувати звичайну функцію indexOf, щоб побачити, чи містить список класів інший рядок.


1
Що з тестуванням для класу classу наведеному вище прикладі?
Фелікс Клінг

6
З досвіду цей метод може бути досить ризикованим: він повернеться істинним, коли шукатимеш клас fooна елементі, який має foobarклас.
Зірак

2
Звичайно, ви просто знаєте, що ви тестуєте. Код Фелікса добре працює, використовуючи пробіли як роздільник.
Девід

Неможливо врахувати вкладені екземпляри імені класу. Приклад: 'end' можна знайти у назві класу 'frontend'.
Ентоні Рутлідж

4

Я знаю, що відповідей дуже багато, але більшість із них призначені для додаткових функцій та додаткових занять. Це я особисто використовую; набагато чистіше і набагато менше рядків коду!

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

1
цей метод може повернути помилкові позитиви при пошуку імені класу, яке частково збігається - наприклад, <body class="category-page">і document.body.className.match('page')- буде відповідати, але pageдо елемента не додається клас
hooblei

Можна вирішити \b, наприклад /\bpage\b/g, оскільки це регулярний вираз (примітка: доведеться використовувати / /g).
Андрій

2

Ось тривіальне рішення, що не враховує регістр:

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

2

Якщо елемент має лише одне ім’я класу, ви можете швидко перевірити його, отримавши атрибут класу. Інші відповіді набагато надійніші, але це, безумовно, є випадки використання.

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

}

2

Я створив метод-прототип, який використовує 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>

Тестова сторінка


Чи є причина, чому ви хочете використовувати список класів замість індексу e.className? Здається, парфуми менш хороші
Ced

@Ced - ну, perf не має значення, якщо ви не тестуєте тисячі елементів для їх класу (це, мабуть, буде відновлено у веб-переглядачах у майбутньому). це більш елегантно використовувати, оскільки код описує його функціональність, але
підсумок

1
  1. Хитрість Фелікса в додаванні пробілів для розшарування 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, можна виконувати код, коли є збіг - так що, якщо елемент має, fi, class1 і class2, будуть виконуватися і fn1, і fn2.
    • Перевага такого підходу полягає в тому, що код, який потрібно виконати для кожного класу, є довільним, як і той, що знаходиться в операторі switch; у вашому прикладі всі випадки виконували подібну операцію, але завтра вам може знадобитися зробити різні речі для кожного.
    • Ви можете імітувати випадок за замовчуванням, маючи змінну стану, яка вказує, чи було знайдено відповідність у циклі чи ні.

1

Я б Полі заповнив функцію classList і використав новий синтаксис. Таким чином новіший браузер використовуватиме нову реалізацію (що набагато швидше), і лише старі веб-переглядачі візьмуть за показник ефективність від коду.

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


1

Це трохи відключено, але якщо у вас подія, яка викликає перемикання, ви можете обійтися без занять:

<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.

Це трохи хакі, але працює для довгих комутаторів без додаткових функцій або циклів


1

Дивіться це посилання Codepen для більш швидкого і простого способу перевірки елемента, якщо він має певний клас за допомогою ванільного JavaScript ~!

hasClass (Vanilla JS)

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

1

Це підтримується на IE8 +.

Спочатку ми перевіряємо, чи classListіснує, чи можна, ми можемо використовувати containsметод, який підтримується IE10 +. Якщо ми перебуваємо на IE9 або 8, це повертається до використання регулярного вираження, яке не є настільки ефективним, але є стислим поліфілом.

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

Крім того, якщо ви компілюєте з babel, ви можете просто використовувати: el.classList.contains(className);


0

Спробуйте це:

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

1
Будьте обережні зі словом межа. Він також відповідає істині, якщо у вас є, наприклад, клас foo-barта пошук foo.
Фелікс Клінг

1
Привіт Джимі, тому я шукав цей \ b метахарактер, і він вважає лише [ a-zA-Z0-9_] символами слова. Тож для імен класів, що містять мінус графік, це не працюватиме .
Стано

0

Я думаю, що ідеальним рішенням буде це

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

8
1. "Використання простого JavaScript (не jQuery)" 2. Використовуйте дужки
nkmol

3 - використовуйте Парентез
TheBlackBenzKid

0

в якому елементі зараз клас ".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

Звичайно, це лише пошук 1 простого елемента <img>( /Image/g), але ви можете помістити все в масив, як <li>є /LI/g, <ul>= /UL/gі т.д.


0

Просто для додання відповіді для людей, які намагаються знайти імена класів у вбудованих елементах SVG.

Змініть hasCLass()функцію на:

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

Замість використання classNameвластивості вам потрібно буде використовувати getAttribute()метод, щоб схопити ім'я класу.


0

Я створив ці функції для свого веб-сайту, використовую лише ванільний 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')

Сподіваюся, це допоможе.


0

Порада: Спробуйте максимально усунути залежності jQuery у своїх проектах - VanillaJS .

document.firstElementChildreturn <html>тег, тоді classListатрибут повертає всі додані до нього класи.

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

-1

Для мене найелегантніший і швидший спосіб досягти цього:

function hasClass(el,cl){
   return !!el.className && !!el.className.match(new RegExp('\\b('+cl+')\\b'));
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.