JQuery .hasClass dla wielu wartości w instrukcji if

81

Mam proste stwierdzenie if jako takie:

if ($('html').hasClass('m320')) {

// do stuff 

}

Działa to zgodnie z oczekiwaniami. Chciałbym jednak dodać więcej klas do tagu, if statementaby sprawdzić, czy którakolwiek z klas jest obecna w <html>tagu. Potrzebuję tego, więc to nie wszystkie, ale obecność co najmniej jednej klasy, ale może być więcej.

Mój przypadek użycia jest, że mam zajęcia (np m320, m768) dodanego do różnych szerokościach rzutni więc chcę tylko, aby wykonać pewną Jquery jeśli jest to specyficzna szerokość (klasa).

Oto, czego próbowałem do tej pory:

1.

if ($('html').hasClass('m320', 'm768')) {

// do stuff 

}

2.

if ($('html').hasClass('m320')) || ($('html').hasClass('m768')) {

 // do stuff 

}

3.

 if ($('html').hasClass(['m320', 'm768'])) {

 // do stuff 

    }

Jednak żaden z nich nie działa. Nie jestem pewien, co robię źle, ale najprawdopodobniej moja składnia lub struktura.

Danny Englander
źródło
1
Zamiast zgadywać, jak działa API, powinieneś przeczytać dokumentację. api.jquery.com/hasclass Ponadto konsola programisty powinna być pod ręką / otwarta podczas programowania .
klify szaleństwa

Odpowiedzi:

74

W drugiej próbie masz pomieszane nawiasy.

var $html = $("html");

if ($html.hasClass('m320') || $html.hasClass('m768')) {

  // do stuff 

}
James Montagne
źródło
6
Naprawdę powinieneś buforować $('html')zmienną, zamiast szukać jej wielokrotnie.
epascarello
1
@epascarello To prawda, aktualizuję odpowiedź dla potomnych.
James Montagne
163

Możesz użyć is()zamiast hasClass():

if ($('html').is('.m320, .m768')) { ... }
elclanrs
źródło
3
Tak hasClass()jest prawdopodobnie szybsze, ale is()jest o wiele wygodniejsze w większości przypadków
elclanrs
1
BTW tutaj możemy zobaczyć testy wydajności dla is()ihasClass()
Jignesh Gohel
1
Jest więc dużo wolniejszy, ale ogólnie bardzo szybki. Jeśli skanowanych jest tylko kilka elementów, wydaje się, że nie jest to wielka sprawa dla znacznie czystszego kodu.
jerclarke
28

Dla zabawy napisałem małą dodatkową metodę jQuery, która sprawdzi jedną z wielu nazw klas:

$.fn.hasAnyClass = function() {
    for (var i = 0; i < arguments.length; i++) {
        if (this.hasClass(arguments[i])) {
            return true;
        }
    }
    return false;
}

Następnie w swoim przykładzie możesz użyć tego:

if ($('html').hasAnyClass('m320', 'm768')) {

// do stuff 

}

Możesz przekazać dowolną liczbę nazw klas.


Oto ulepszona wersja, która umożliwia również przekazywanie wielu nazw klas oddzielonych spacją:

$.fn.hasAnyClass = function() {
    for (var i = 0; i < arguments.length; i++) {
        var classes = arguments[i].split(" ");
        for (var j = 0; j < classes.length; j++) {
            if (this.hasClass(classes[j])) {
                return true;
            }
        }
    }
    return false;
}

if ($('html').hasAnyClass('m320 m768')) {
    // do stuff 
}

Działające demo: http://jsfiddle.net/jfriend00/uvtSA/

jfriend00
źródło
Świetnie, to działa dobrze ... także w różnych przeglądarkach! Testowane na FF i IE.
crmpicco,
Zrobiłem niewielką modyfikację, aby była zgodna z konwencjami jQuery dla .addClass i .removeClass (). ( stackoverflow.com/a/14887517/170456 )
CyberMonk,
25

Może to być inne rozwiązanie:

if ($('html').attr('class').match(/m320|m768/)) {  
  // do stuff   
}  

według jsperf.com jest też dość szybki.

Kolja
źródło
Bardzo ładnie, dużo szybciej!
Filip
9
Będzie to również pasowało do klasy „ZZZm320WWW” i tym podobnych. Spróbuj ... match (/ \ b (m320 | m768) \ b /), gdzie \ b to początek i koniec słowa.
Juan Lanus
tylko po to, aby kontynuować (7 lat później :)). Działa to świetnie, ale jeśli zdefiniowany przez Ciebie element html nie ma żadnych klas - wyskoczy błąd „Nie można odczytać właściwości” dopasuj ”niezdefiniowane”. W takim przypadku sprawdź, czy element ma nawet atrybut „class” (lub sprawdź, czy atrybut „class” nie jest pusty).
Sanya
5

Dla każdego, kto zastanawia się nad niektórymi różnymi aspektami wydajności ze wszystkimi tymi różnymi opcjami, utworzyłem tutaj przypadek jsperf : jsperf

Krótko mówiąc, używanie element.hasClass('class') jest najszybsze.

Następny najlepszy zakład to użycie elem.hasClass('classA') || elem.hasClass('classB') . Uwaga na ten temat: porządek ma znaczenie! Jeśli istnieje większe prawdopodobieństwo znalezienia klasy „classA”, wymień ją najpierw! Instrukcje warunku OR są zwracane, gdy tylko jeden z nich zostanie spełniony.

Zdecydowanie najgorsza wydajność element.is('.class') .

W jsperf znajduje się również funkcja CyberMonk i rozwiązanie Kolji .

Ryan Steffer
źródło
Naprawdę interesujące! Nie miałem pojęcia o jsperf. Dziękuję za zilustrowanie wszystkich różnych odmian.
Danny Englander
3

Oto niewielka odmiana odpowiedzi oferowanej przez jfriend00:

$.fn.hasAnyClass = function() {
    var classes = arguments[0].split(" ");
    for (var i = 0; i < classes.length; i++) {
        if (this.hasClass(classes[i])) {
            return true;
        }
    }
    return false;
}

Pozwala na użycie tej samej składni co .addClass () i .removeClass (). np. .hasAnyClass('m320 m768') oczywiście wymaga kuloodporności, ponieważ zakłada co najmniej jeden argument.

CyberMonk
źródło
0
var classes = $('html')[0].className;

if (classes.indexOf('m320') != -1 || classes.indexOf('m768') != -1) {
    //do something
}
adeneo
źródło
1
Jeśli masz zamiar to zrobić, po co w ogóle zawracać sobie głowę korzystaniem z jquery, aby uzyskać element?
James Montagne
Cóż, nie zrobiłbym tego, ale przynajmniej dostaje zajęcia tylko raz? Po prostu wydawało się to nudne bez odrobiny jQuery, więc zastąpiłem getElementsByTagName odrobiną magii jQ specjalnie dla Ciebie!
adeneo
0

Metoda hasClass przyjmie tablicę nazw klas jako argument, możesz zrobić coś takiego:

$(document).ready(function() {
function filterFilesList() {
    var rows = $('.file-row');
    var checked = $("#filterControls :checkbox:checked");

    if (checked.length) {
        var criteriaCollection = [];

        checked.each(function() {
            criteriaCollection.push($(this).val());
        });

        rows.each(function() {
            var row = $(this);
            var rowMatch = row.hasClass(criteriaCollection);

            if (rowMatch) {
                row.show();
            } else {
                row.hide(200);
            }
        });
    } else {
        rows.each(function() {
            $(this).show();
        });
    }
}

    $("#filterControls :checkbox").click(filterFilesList);
    filterFilesList();
});
Ron Sims II
źródło
0

Dzieje się tak na wypadek, gdybyś potrzebował obu klas. Dla logiki albo albo po prostu użyj ||

$('el').hasClass('first-class') || $('el').hasClass('second-class')

W razie potrzeby możesz zoptymalizować

qwerty_igor
źródło
1
To jest źle. Pierwszy przykład, który podałeś, działa tylko dlatego, że metoda ma słabe oczyszczanie danych wejściowych i uważa, że ​​cały ciąg jest nazwą klasy. Nie działa, jeśli zajęcia są w innej kolejności lub nie znajdują się obok siebie. Zobacz przykład: jsfiddle.net/0d57ekty
MightyPork
@MightyPork dzięki za sprawdzenie. masz rację, powinno być używane tylko w klasie
qwerty_igor
-1

Spróbuj tego:

if ($('html').hasClass('class1 class2')) {

// do stuff 

}
Robert Łoziński
źródło
Witamy w Stack Overflow! Proszę dodać wyjaśnienie, dlaczego ten kod pomaga OP. Pomoże to znaleźć odpowiedź, z której przyszli widzowie będą mogli się czegoś nauczyć. Aby uzyskać więcej informacji, zobacz Jak odpowiedzieć .
Heretic Monkey