Przed dodaniem sprawdź, czy klasa jest już przypisana

113

Czy w jQuery zaleca się sprawdzenie, czy klasa jest już przypisana do elementu przed dodaniem tej klasy? Czy to w ogóle będzie miało jakiś efekt?

Na przykład:

<label class='foo'>bar</label>

W razie wątpliwości, czy klasa bazzostała już przypisana label, czy byłoby to najlepsze podejście:

var class = 'baz';
if (!$('label').hasClass(class)) {
  $('label').addClass(class);
}

czy to wystarczy:

$('label').addClass('baz');
Muleskinner
źródło
12
Używałem .hasClasstylko wtedy, gdy muszę sprawdzić, czy klasa istnieje, jeśli muszę tylko przypisać klasę - używam .addClass. jQuery nie powiela klas
Samich,
7
Po prostu dodaj klasę bez testowania. Jeśli już istnieje, nie zostanie ponownie dodany.
Blazemonger

Odpowiedzi:

177

Po prostu zadzwoń addClass(). jQuery zrobi to za Ciebie. Jeśli sprawdzasz samodzielnie, podwajasz pracę, ponieważ jQuery nadal przeprowadzi sprawdzanie za Ciebie.

jmar777
źródło
47

Proste sprawdzenie w konsoli powiedziałoby ci, że addClasswielokrotne dzwonienie z tą samą klasą jest bezpieczne.

W szczególności możesz znaleźć czek w źródle

if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
  setClass += classNames[ c ] + " ";
}
Raynos
źródło
2
Przeczytaj ponownie moje pytanie, a zauważysz, że nie chodzi o bezpieczeństwo, ale o najlepszą praktykę
Muleskinner
7
Z redagowanej odpowiedzi widzę, że jQuery faktycznie sprawdza, czy klasa jest już przypisana przed jej dodaniem, tj. Byłoby złą praktyką samodzielne sprawdzanie / dziękuję
Muleskinner
5
@Muleskinner to właśnie sugerowałem.
Raynos,
41
@Raynos: Proste sprawdzenie w konsoli powiedziałoby ci, że wielokrotne wywoływanie addClass z tą samą klasą jest bezpieczne. Mimo to, to pytanie było jednym z największych hitów, kiedy szukałem odpowiedzi w Google ... Nawet błahe rzeczy, które są dobrze udokumentowane w innym miejscu, nie mają miejsca w Stack Overflow.
eirirlar
10
W tej odpowiedzi jest zdecydowanie za dużo nastawienia. Mógłby odpowiedzieć na to taktem.
dreadwail
4

To pytanie zwróciło moją uwagę po kolejnym, które zostało oznaczone jako duplikat tego .

Ta odpowiedź podsumowuje zaakceptowaną odpowiedź z niewielkimi dodatkowymi szczegółami.

Próbujesz zoptymalizować, unikając niepotrzebnego sprawdzania, w związku z tym oto czynniki, o których musisz wiedzieć:

  1. nie można mieć zduplikowanych nazw klas w atrybucie klasy poprzez manipulowanie elementem DOM za pomocą JavaScript. Jeśli masz class="collapse"w kodzie HTML, wywołanie Element.classList.add("collapse");nie spowoduje dodania dodatkowej klasy zwijania . Nie znam podstawowej implementacji, ale przypuszczam, że powinna być wystarczająco dobra.
  2. JQuery dokonuje niezbędnych kontroli w swoim addClassi removeClassimplementacjach (sprawdziłem kod źródłowy ). Po addClasswykonaniu pewnych sprawdzeń i jeśli klasa istnieje, JQuery nie próbuje jej ponownie dodać. Podobnie w przypadku removeClassJQuery robi coś, cur.replace( " " + clazz + " ", " " );co powoduje usunięcie klasy tylko wtedy, gdy istnieje.

Warto zauważyć, że JQuery przeprowadza pewną optymalizację swojej removeClassimplementacji, aby uniknąć bezcelowego ponownego renderowania. Tak to wygląda

...
// only assign if different to avoid unneeded rendering.
finalValue = value ? jQuery.trim( cur ) : "";
if ( elem.className !== finalValue ) {
    elem.className = finalValue;
}
...

Zatem najlepszą mikrooptymalizacją, jaką można by zrobić, byłaby uniknięcie narzutu wywołań funkcji i związanych z nimi kontroli implementacji.

Powiedzmy, że chcesz zmienić klasę o nazwie collapse, jeśli masz pełną kontrolę nad tym, kiedy klasa jest dodawana lub usuwana, a jeśli collapseklasa jest początkowo nieobecna, możesz zoptymalizować w następujący sposób:

$(document).on("scroll", (function () {
    // hold state with this field
    var collapsed = false;

    return function () {
        var scrollTop, shouldCollapse;

        scrollTop = $(this).scrollTop();
        shouldCollapse = scrollTop > 50;

        if (shouldCollapse && !collapsed) {
            $("nav .branding").addClass("collapse");
            collapsed = true;

            return;
        }

        if (!shouldCollapse && collapsed) {
            $("nav .branding").removeClass("collapse");
            collapsed = false;
        }
    };
})());

Na marginesie, jeśli przełączasz klasę z powodu zmian w pozycji przewijania, zdecydowanie zalecamy ograniczenie obsługi zdarzeń przewijania.

Igwe Kalu
źródło
1
$("label")
  .not(".foo")
  .addClass("foo");
טאבו ישראל שרות לקוחות
źródło