Перевірте, чи містить елемент клас у 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.