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.