Czy istnieje sposób dodawania / usuwania kilku klas w jednej instrukcji za pomocą classList?


164

Do tej pory muszę to zrobić:

elem.classList.add("first");
elem.classList.add("second");
elem.classList.add("third");

Chociaż jest to wykonalne w jQuery, w ten sposób

$(elem).addClass("first second third");

Chciałbym wiedzieć, czy istnieje jakiś natywny sposób dodawania lub usuwania.

Odpowiedzi:


314
elem.classList.add("first");
elem.classList.add("second");
elem.classList.add("third");

jest równy

elem.classList.add("first","second","third");

15
A jeśli chcesz zastosować tablicę kilku nazw klas, musisz wywołać: DOMTokenList.prototype.add.apply (elem.classList, ['pierwsza', 'druga', 'trzecia']);
Emanuel Kluge,

8
Firefox też go nie obsługuje w momencie pisania. Moja odpowiedź zawiera wypełnienie.
Andy E

Przełączam się na ten jako poprawną odpowiedź, ponieważ jest to natywny interfejs API, nawet jeśli obsługa nie jest świetna.
Namiot Enrique Moreno

1
Czy rozważałeś el.className + = "moje zajęcia tutaj"
Michael Tontchev

1
czy istnieje sposób na usunięcie wielu klas
MeVimalkumar,

72

Nowy operator spreadu jeszcze bardziej ułatwia stosowanie wielu klas CSS jako tablicy:

const list = ['first', 'second', 'third'];
element.classList.add(...list);

1
Zaakceptowana odpowiedź działa z bezpośrednią listą wartości, ale ta działa z tablicami ... obie wydają się doskonałe odpowiedzi!
Namiot Enrique Moreno

Czy mogę użyć DOMTokenListzamiast tablicy? Wiem, że DOMTokenList jest obiektem przypominającym tablicę. Czy jest możliwe użycie tej classList.add()metody z tą metodą, czy też DOMTokenList musi zostać przekonwertowany na rzeczywistą tablicę?
xela84

19

classListWłaściwość zapewnia, że zduplikowane klasy nie są niepotrzebnie dodany do elementu. Aby zachować tę funkcjonalność, jeśli nie lubisz wersji odręcznych lub wersji jQuery, proponuję dodać addManyfunkcję i removeManydo DOMTokenList(rodzaj classList):

DOMTokenList.prototype.addMany = function(classes) {
    var array = classes.split(' ');
    for (var i = 0, length = array.length; i < length; i++) {
      this.add(array[i]);
    }
}

DOMTokenList.prototype.removeMany = function(classes) {
    var array = classes.split(' ');
    for (var i = 0, length = array.length; i < length; i++) {
      this.remove(array[i]);
    }
}

Te byłyby użyteczne w następujący sposób:

elem.classList.addMany("first second third");
elem.classList.removeMany("first third");

Aktualizacja

Zgodnie z Twoimi komentarzami, jeśli chcesz napisać niestandardową metodę tylko na wypadek, gdyby nie zostały zdefiniowane, spróbuj wykonać następujące czynności:

DOMTokenList.prototype.addMany = DOMTokenList.prototype.addMany || function(classes) {...}
DOMTokenList.prototype.removeMany = DOMTokenList.prototype.removeMany || function(classes) {...}

Wciąż dobra odpowiedź. Nie mogłem tego dla Ciebie edytować, ponieważ zawierały tylko 2 znaki.
Pete,

18

Ponieważ add()metoda z classListjust pozwala na przekazywanie oddzielnych argumentów, a nie pojedynczej tablicy, musisz wywołać funkcję add()apply. Jako pierwszy argument musisz przekazać classListreferencję z tego samego węzła DOM, a jako drugi argument tablicę klas, które chcesz dodać:

element.classList.add.apply(
  element.classList,
  ['class-0', 'class-1', 'class-2']
);

Jest to wersja rozwiązania ES5 z operatorem spreadu (patrz odpowiedź @morkro ). Sprawdź to łatwo w Babel Repl .
Nickensoul

7

Aby dodać klasę do elementu

document.querySelector(elem).className+=' first second third';

AKTUALIZACJA:

Usuń zajęcia

document.querySelector(elem).className=document.querySelector(elem).className.split(class_to_be_removed).join(" ");

Warto to wiedzieć, ale wszystko, co robi, to edycja ciągu znaków klasy. Nie zadziałałoby, gdybym chciał usunąć kilka klas. Przepraszam, zapomniałem dodać to w OP.
Namiot Enrique Moreno

4
Czy nie używać className. Jest to straszne dla wydajności (nawet odzyskanie jego wartości powoduje rozpływ).
jacob

7

Nowsze wersje specyfikacji DOMTokenList pozwalają na użycie wielu argumentów do add()i remove(), a także drugiego argumentu toggle()do wymuszenia stanu.

W chwili pisania tego tekstu Chrome obsługuje wiele argumentów do add()i remove(), ale żadna z innych przeglądarek nie obsługuje. IE 10 i starsze, Firefox 23 i starsze, Chrome 23 i starsze oraz inne przeglądarki nie obsługują drugiego argumentu do toggle().

Napisałem następujący mały polyfill, aby poprowadzić mnie do momentu rozszerzenia wsparcia:

(function () {
    /*global DOMTokenList */
    var dummy  = document.createElement('div'),
        dtp    = DOMTokenList.prototype,
        toggle = dtp.toggle,
        add    = dtp.add,
        rem    = dtp.remove;

    dummy.classList.add('class1', 'class2');

    // Older versions of the HTMLElement.classList spec didn't allow multiple
    // arguments, easy to test for
    if (!dummy.classList.contains('class2')) {
        dtp.add    = function () {
            Array.prototype.forEach.call(arguments, add.bind(this));
        };
        dtp.remove = function () {
            Array.prototype.forEach.call(arguments, rem.bind(this));
        };
    }

    // Older versions of the spec didn't have a forcedState argument for
    // `toggle` either, test by checking the return value after forcing
    if (!dummy.classList.toggle('class1', true)) {
        dtp.toggle = function (cls, forcedState) {
            if (forcedState === undefined)
                return toggle.call(this, cls);

            (forcedState ? add : rem).call(this, cls);
            return !!forcedState;
        };
    }
})();

Nowoczesna przeglądarka zgodna z ES5 i DOMTokenListoczekiwana, ale używam tego polyfill w kilku specjalnie ukierunkowanych środowiskach, więc działa świetnie, ale może wymagać poprawek dla skryptów, które będą działać w starszych środowiskach przeglądarek, takich jak IE 8 i starsze .


1
Wydaje się, że nikt nie wspomina, że ​​IE10 nie pozwala na dodawanie wielu klas. To działało dobrze dla mnie, więc dzięki! Ostrzegałbym jednak, że w IE9 pojawia się błąd, że DomTokenList nie jest zdefiniowany. Możesz z tego też skorzystać. Lub uruchom to tylko wtedy, gdy (typeof DomTokenList! == 'undefined')
Ryan Ore

@Ryan: dzięki, myślałem, że DOMTokenList jest obsługiwany w IE 9, ale myślę, że został pominięty. W pewnym momencie spróbuję zbadać obejście problemu.
Andy E

Wygląda na to, że na nieudanej liście DOMTokenList musiałbyś użyć className z sprawdzeniami regEx granicy słowa
Greg

7

Możesz zrobić jak poniżej

Dodaj

elem.classList.add("first", "second", "third");

Usunąć

elem.classList.remove("first", "second", "third");

Odniesienie

TLDR;

W prostym przypadku powyższe usuwanie powinno działać. Ale w przypadku usunięcia należy upewnić się, że klasa istnieje, zanim je usuniesz

const classes = ["first","second","third"];
classes.forEach(c => {
  if (elem.classList.contains(c)) {
     element.classList.remove(c);
  }
})

5

Oto obejście dla użytkowników IE 10 i 11, które wydawało się dość proste.

var elem = document.getElementById('elem');

['first','second','third'].map(item => elem.classList.add(item));
<div id="elem">Hello World!</div>

Lub

var elem = document.getElementById('elem'),
    classes = ['first','second','third'];

classes.map(function(item) {
    return elem.classList.add(item);
});
<div id="elem">Hello World!</div>


5
Dobry pomysł. Użyłbym jednak .forEach () zamiast .map () - jest to czystsze / bardziej wydajne w sytuacjach takich jak ta, w których nie używasz zwróconej tablicy.
tenni

Tak to prawda.
colecmc

2

Standardowa definicja pozwala tylko na dodanie lub usunięcie jednej klasy. Kilka małych funkcji opakowania może zrobić to, o co prosisz:

function addClasses (el, classes) {
  classes = Array.prototype.slice.call (arguments, 1);
  console.log (classes);
  for (var i = classes.length; i--;) {
    classes[i] = classes[i].trim ().split (/\s*,\s*|\s+/);
    for (var j = classes[i].length; j--;)
      el.classList.add (classes[i][j]);
  }
}

function removeClasses (el, classes) {
  classes = Array.prototype.slice.call (arguments, 1);
  for (var i = classes.length; i--;) {
    classes[i] = classes[i].trim ().split (/\s*,\s*|\s+/);
    for (var j = classes[i].length; j--;)
      el.classList.remove (classes[i][j]);
  }
}

Te opakowania pozwalają określić listę klas jako oddzielne argumenty, ciągi znaków z elementami oddzielonymi spacjami lub przecinkami lub ich kombinację. Na przykład patrz http://jsfiddle.net/jstoolsmith/eCqy7


2

Bardzo proste, nie wyszukane, ale działające rozwiązanie, w które musiałbym wierzyć, jest bardzo cross-browser:

Utwórz tę funkcję

function removeAddClasses(classList,removeCollection,addCollection){
    for (var i=0;i<removeCollection.length;i++){ 
        classList.remove(removeCollection[i]); 
    }
    for (var i=0;i<addCollection.length;i++){ 
        classList.add(addCollection[i]); 
    }
}

Nazwij to tak: removeAddClasses (node.classList, arrayToRemove, arrayToAdd);

... gdzie arrayToRemove jest tablicą nazw klas do usunięcia: ['myClass1', 'myClass2'] etcetera

... a arrayToAdd to tablica nazw klas do dodania: [„myClass3”, „myClass4”] itd.


1

Załóżmy, że masz tablicę klas do dodania, możesz użyć składni rozszerzania ES6:

let classes = ['first', 'second', 'third']; elem.classList.add(...classes);


0

Podobała mi się odpowiedź @ rich.kelly, ale chciałem użyć tej samej nomenklatury co classList.add()(ciągi oddzielone przecinkami), więc niewielkie odchylenie.

DOMTokenList.prototype.addMany = DOMTokenList.prototype.addMany || function() {
  for (var i = 0; i < arguments.length; i++) {
    this.add(arguments[i]);
  }
}
DOMTokenList.prototype.removeMany = DOMTokenList.prototype.removeMany || function() {
  for (var i = 0; i < arguments.length; i++) {
    this.remove(arguments[i]);
  }
}

Możesz więc użyć:

document.body.classList.addMany('class-one','class-two','class-three');

Muszę przetestować wszystkie przeglądarki, ale to zadziałało w przypadku Chrome.
Czy powinniśmy szukać czegoś bardziej konkretnego niż istnienie DOMTokenList.prototype.addMany? Co dokładnie powoduje classList.add()niepowodzenie w IE11?


0

Kolejny polifill dla element.classListjest tutaj . Znalazłem to przez MDN .

Dołączam ten skrypt i używam element.classList.add("first","second","third")go zgodnie z przeznaczeniem.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.