Kiểm tra xem một phần tử có chứa một lớp trong JavaScript không?


588

Sử dụng JavaScript đơn giản (không phải jQuery), Có cách nào để kiểm tra xem một phần tử có chứa một lớp không?

Hiện tại, tôi đang làm điều này:

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>

Vấn đề là nếu tôi thay đổi HTML thành ...

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

... không còn khớp chính xác nữa, vì vậy tôi nhận được đầu ra mặc định là nothing ( ""). Nhưng tôi vẫn muốn đầu ra được I have class1<div>vẫn chứa các .class1lớp.


5
Element. classList.contains (cls)
Ronnie Royston

Câu trả lời:


1039

Sử dụng phương pháp:element.classList .contains

element.classList.contains(class);

Điều này hoạt động trên tất cả các trình duyệt hiện tại và cũng có các polyfill để hỗ trợ các trình duyệt cũ hơn.


Ngoài ra , nếu bạn làm việc với các trình duyệt cũ hơn và không muốn sử dụng polyfill để sửa chúng, sử dụng indexOflà chính xác, nhưng bạn phải điều chỉnh một chút:

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

Nếu không, bạn cũng sẽ nhận được truenếu lớp bạn đang tìm là một phần của tên lớp khác.

BẢN GIỚI THIỆU

jQuery sử dụng một phương thức tương tự (nếu không giống nhau).


Áp dụng cho ví dụ:

Vì điều này không hoạt động cùng với câu lệnh chuyển đổi, bạn có thể đạt được hiệu ứng tương tự với mã này:

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

Nó cũng ít dư thừa hơn;)


Tuyệt vời, nhưng làm cách nào để sử dụng kết hợp với câu lệnh chuyển đổi để tôi có thể thay đổi đầu ra dựa trên các lớp mà div chứa?
daGUY

@daGUY: Bạn muốn làm gì với câu lệnh switch? Ví dụ: Thứ hai divcó hai lớp nhưng nó sẽ chỉ xuất ra I have class1khi bạn đang sử dụng break. Nếu bạn muốn xuất ra mỗi lớp một phần tử có, thì bạn chỉ cần lấy classNamevà chia nó trên các khoảng trắng. Hay mục tiêu thực sự của bạn là gì?
Felix Kling

@Felix Kling: Tôi cần div bên trong của div để thay đổi giữa bốn chuỗi khác nhau tùy thuộc vào loại nó chứa. Tôi chỉ sử dụng "Tôi có class1", v.v. làm ví dụ - các chuỗi thực đều khác nhau. Tôi sẽ chỉ hiển thị một chuỗi tại một thời điểm, không kết hợp bất kỳ chuỗi nào (do đó nghỉ sau mỗi trường hợp). Tôi chỉ muốn nó vẫn hoạt động ngay cả khi lớp phù hợp là một trong nhiều lớp trên div.
daGUY

@Felix Kling: đã làm được, cảm ơn rất nhiều! Tôi thực sự không xuất ra tên của các lớp, mà là một trong bốn chuỗi hoàn toàn khác nhau, vì vậy tôi đã sửa đổi nó một chút với một vài câu lệnh IF / ELSE IF để xử lý từng chuỗi. Hoạt động hoàn hảo mặc dù.
daGUY

1
Có một lý do cụ thể tại sao bạn thêm không gian trước và sau?
Ced

93

Các giải pháp dễ dàng và hiệu quả là thử phương pháp .contains .

test.classList.contains(testClass);

3
các containsphương pháp của một element.classListbất động sản
user907860

7
Lưu ý! Không được hỗ trợ trong tất cả các trình duyệt, thêm thông tin tại đây: caniuse.com/#feat=
classlist

4
Đây là một câu trả lời tuyệt vời và tôi tin rằng .contains () có sự hỗ trợ rộng lớn hơn nhiều.
Nicholas Kreidberg

49

Trong các trình duyệt hiện đại, bạn chỉ có thể sử dụng containsphương pháp Element.classList:

testElement.classList.contains(className)

Bản giới thiệu

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>


Các trình duyệt được hỗ trợ

nhập mô tả hình ảnh ở đây

(từ CanIUse.com )


Polyfill

Nếu bạn muốn sử dụng Element.classListnhưng bạn cũng muốn hỗ trợ các trình duyệt cũ hơn, hãy xem xét sử dụng polyfill này của Eli Gray .


10

Vì anh ấy muốn sử dụng switch (), tôi ngạc nhiên chưa có ai đưa ra điều này:

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
Tôi chỉ đang tự hỏi điều tương tự, nhưng đúng, đó là vấn đề gần nhất với vấn đề ban đầu!
Bạc Ringvee

8

Element.matches ()

Element.matches (selectorString)

Theo Tài liệu web MDN :

Các Element.matches()trở về phương pháp truenếu yếu tố này sẽ được lựa chọn bởi các chuỗi selector quy định; nếu không, trả lại false.

Do đó, bạn có thể sử dụng Element.matches()để xác định xem một phần tử có chứa một lớp hay không.

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

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

Xem tương thích trình duyệt


7

Đây là một đoạn nhỏ Nếu bạn đang cố kiểm tra phần tử wether có chứa một lớp mà không sử dụng jQuery.

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

Điều này cho thấy thực tế là phần tử có thể chứa nhiều tên lớp được phân tách bằng dấu cách.

HOẶC LÀ


Bạn cũng có thể gán chức năng này cho nguyên mẫu phần tử.

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

Và kích hoạt nó như thế này (rất giống với .hasClass()chức năng của jQuery ):

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

Tôi thích giải pháp này hơn. Nó tránh được vấn đề tên lớp khớp một phần với lớp khác và không yêu cầu polyfill hoạt động trong IE.
scoota269

5

Một oneliner đơn giản hóa: 1

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

1 indexOf cho mảng không được IE (ofcference) hỗ trợ. Có rất nhiều bản vá khỉ được tìm thấy trên mạng cho điều đó.


1
Vấn đề với các ranh giới từ là một số ký tự hợp lệ cho các tên lớp như -được coi là ranh giới từ. Ví dụ tìm kiếm foovà lớp là foo-barnăng suất true.
Felix Kling

Bạn đúng rồi. Loại bỏ bản gốc, thêm một cách tiếp cận khác. Vẫn là một oneliner.
KooiInc

5

Điều này hơi cũ, nhưng có lẽ ai đó sẽ tìm thấy giải pháp hữu ích của tôi:

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

sử dụng: 'phần tử.hasClass (' tên lớp ');
Mất trí nhớ

Tại sao bạn sử dụng t.length >>> 0? Theo như tôi biết thì đó là một noop nếu bạn sử dụng '0', phải không?
Vitor Canova

wow rất nhiều mã cho một cái gì đó đơn giản. Tại sao không sử dụng một biểu thức thông thường và không phát minh lại bánh xe? bạn chỉ có thể sử dụng / ^ class_name_you_are_searching_for$/.test(myEuity. className)
pqsk

1
Tôi đã viết nó quá nhanh. Chỉ cần không overcomplicate biểu hiện thường xuyên của tôi nó sẽ là /\s*class_name_you_are_searching_for\s*/.test(myElement.className)
pqsk

@pqsk - tôi viết thư viện của riêng tôi để sử dụng trong tương lai. và điều này chỉ thêm vào ngăn xếp của tôi. tất nhiên các giải pháp khác sẽ hoạt động, đây chỉ là cách ưa thích của tôi
Dementic

4

classNamechỉ là một chuỗi để bạn có thể sử dụng hàm indexOf thông thường để xem danh sách các lớp có chứa một chuỗi khác không.


1
Điều gì về kiểm tra cho lớp classtrong ví dụ trên?
Felix Kling

6
Từ kinh nghiệm, phương pháp này có thể khá rủi ro: Nó sẽ trả về đúng khi bạn tìm lớp footrên một phần tử có foobarlớp.
Zirak

2
Chắc chắn, bạn chỉ cần nhận thức được những gì bạn đang thử nghiệm. Mã của Felix hoạt động tốt bằng cách sử dụng khoảng trắng làm dấu phân cách.
David

Không thể tính đến các trường hợp lồng nhau của một tên lớp. Ví dụ: 'end' có thể được tìm thấy trong tên lớp 'frontend'.
Anthony Rutledge

4

Tôi biết có rất nhiều câu trả lời nhưng hầu hết trong số này là cho các chức năng bổ sung và các lớp bổ sung. Đây là cái mà cá nhân tôi sử dụng; sạch hơn nhiều và ít dòng mã hơn!

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

1
phương thức này có thể trả về dương tính giả khi tìm kiếm tên lớp khớp một phần - ví dụ <body class="category-page">document.body.className.match('page')- sẽ khớp nhưng không có lớp nào được pagegắn với phần tử
hooblei

Có thể được giải quyết bằng \b, ví dụ /\bpage\b/g, vì đó là regex (lưu ý: phải sử dụng / /g).
Andrew

2

Đây là một giải pháp tầm thường không phân biệt chữ hoa chữ thường:

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

Nếu phần tử chỉ có một tên lớp, bạn có thể nhanh chóng kiểm tra nó bằng cách lấy thuộc tính lớp. Các câu trả lời khác mạnh mẽ hơn nhiều nhưng điều này chắc chắn có trường hợp sử dụng.

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

}

2

Tôi đã tạo một phương thức nguyên mẫu sử dụng classList, nếu có thể, các khu nghỉ dưỡng khác để 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>

Trang thử nghiệm


Có lý do nào khiến bạn muốn sử dụng danh sách lớp thay vì chỉ mục của e.groupName không? Có vẻ như sự hoàn hảo là ít tốt hơn
Ced

@Ced - tốt, hoàn hảo là không liên quan nếu bạn không kiểm tra hàng ngàn yếu tố cho lớp của họ, (có thể nó sẽ được tái cấu trúc trong các trình duyệt trong tương lai). Sử dụng thanh lịch hơn vì mã mô tả chức năng của nó, nhưng điểm mấu chốt, không thành vấn đề, hãy làm bất cứ điều gì bạn muốn :)
vsync

1
  1. Thủ thuật của Felix trong việc thêm khoảng trắng vào sườn className và chuỗi bạn đang tìm kiếm là cách tiếp cận phù hợp để xác định xem các phần tử có lớp hay không.

  2. Để có hành vi khác nhau theo lớp, bạn có thể sử dụng tham chiếu hàm hoặc hàm, trong bản đồ:

    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) lặp qua các phím trong bản đồ fns.
    • Không có ngắt sau fnsi cho phép mã được thực thi bất cứ khi nào có khớp - để nếu phần tử có, fi, class1 và class2, cả fn1 và fn2 sẽ được thực thi.
    • Ưu điểm của phương pháp này là mã để thực thi cho mỗi lớp là tùy ý, giống như mã trong câu lệnh switch; trong ví dụ của bạn, tất cả các trường hợp thực hiện một thao tác tương tự, nhưng ngày mai bạn có thể cần phải làm những việc khác nhau cho mỗi trường hợp.
    • Bạn có thể mô phỏng trường hợp mặc định bằng cách có một biến trạng thái cho biết liệu có tìm thấy kết quả khớp trong vòng lặp hay không.


1

Đây là một chút tắt, nhưng nếu bạn có một sự kiện kích hoạt chuyển đổi, bạn có thể làm mà không cần các lớp:

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

Bạn có thể làm

$('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, '')loại bỏ các chữ số từ id.

Đó là một chút hacky, nhưng hoạt động cho các thiết bị chuyển mạch dài mà không có chức năng bổ sung hoặc vòng lặp


1

Xem liên kết Codepen này để biết cách nhanh hơn và dễ dàng kiểm tra một yếu tố nếu nó có một lớp cụ thể bằng cách sử dụng JavaScript vanilla ~!

hasClass (Vanilla JS)

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

1

Điều này được hỗ trợ trên IE8 +.

Đầu tiên chúng tôi kiểm tra xem có classListtồn tại không nếu chúng tôi có thể sử dụng containsphương thức được IE10 + hỗ trợ. Nếu chúng ta đang ở trên IE9 hoặc 8, nó sẽ quay trở lại sử dụng regex, điều này không hiệu quả nhưng là một polyfill ngắn gọn.

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

Ngoài ra, nếu bạn đang biên dịch với babel, bạn chỉ cần sử dụng: el.classList.contains(className);


0

Hãy thử cái này:

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
Hãy cẩn thận với ranh giới từ. Nó cũng sẽ khớp đúng nếu bạn có ví dụ như một lớp foo-barvà tìm kiếm foo.
Felix Kling

1
Xin chào Jimy, vì vậy tôi đã tìm kiếm \ b metacharacter này và nó chỉ coi [ a-zA-Z0-9_] là các ký tự từ. Vì vậy, đối với một tên lớp có chứa một char trừ thì điều này sẽ không hoạt động .
Stano

0

Tôi nghĩ rằng giải pháp hoàn hảo sẽ là

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

8
1. "Sử dụng JavaScript đơn giản (không phải jQuery)" 2. Sử dụng dấu ngoặc
nkmol

3 - sử dụng dấu ngoặc đơn
TheBlackBenzKid

0

trong phần tử nào hiện là lớp '.bar'? Đây là một giải pháp khác nhưng tùy thuộc vào bạn.

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

bản demo jsfiddle

Tất nhiên đây chỉ là một tra cứu cho 1 phần tử đơn giản <img>( /Image/g) nhưng bạn có thể đặt tất cả trong một mảng như <li>/LI/g, <ul>= /UL/g, vv


0

Chỉ cần thêm vào câu trả lời cho những người đang cố gắng tìm tên lớp trong các phần tử SVG nội tuyến.

Thay đổi hasCLass()chức năng thành:

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

Thay vì sử dụng thuộc classNametính, bạn sẽ cần sử dụng getAttribute()phương thức để lấy tên lớp.


0

Tôi đã tạo các chức năng này cho trang web của mình, tôi chỉ sử dụng javilla vanilla, có thể nó sẽ giúp được ai đó. Đầu tiên tôi tạo một hàm để lấy bất kỳ phần tử HTML nào:

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

Sau đó, hàm nhận lớp cần loại bỏ và bộ chọn của phần tử:

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

Bây giờ bạn có thể sử dụng nó như thế này:

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

Hy vọng nó sẽ giúp.


0

Mẹo: Cố gắng loại bỏ sự phụ thuộc của jQuery trong các dự án của bạn nhiều nhất có thể - VanillaJS .

document.firstElementChildtrả về <html>thẻ sau đó classListthuộc tính trả về tất cả các lớp được thêm vào nó.

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

-1

Đối với tôi cách thanh lịch nhất và nhanh hơn để đạt được nó là:

function hasClass(el,cl){
   return !!el.className && !!el.className.match(new RegExp('\\b('+cl+')\\b'));
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.