C'è un modo per aggiungere / rimuovere più classi in una singola istruzione con classList?


164

Finora devo fare questo:

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

Mentre questo è fattibile in jQuery, in questo modo

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

Vorrei sapere se esiste un modo nativo per aggiungere o rimuovere.

Risposte:


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

è uguale

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

15
E se si desidera applicare una matrice di diversi nomi di classe, è necessario chiamare: DOMTokenList.prototype.add.apply (elem.classList, ['first', 'second', 'third']);
Emanuel Kluge,

8
Firefox non lo supporta neanche, al momento della scrittura. La mia risposta fornisce un polyfill.
Andy E

Sto passando a questa come la risposta corretta, poiché si tratta di un'API nativa, anche se il supporto non è eccezionale.
Tenda Enrique Moreno

1
Hai considerato el.className + = "Le mie lezioni qui"
Michael Tontchev,

1
c'è un modo per rimuovere più classi
MeVimalkumar

72

Il nuovo operatore di diffusione semplifica ulteriormente l'applicazione di più classi CSS come array:

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

1
La risposta accettata funziona con un elenco diretto di valori, ma questa funziona con array ... entrambi sembrano risposte eccellenti!
Tenda Enrique Moreno,

Posso usare un DOMTokenListinvece di un array? So che una DOMTokenList è un oggetto simile a un array. Quindi è possibile usarlo con il classList.add()metodo o la DOMTokenList deve essere convertita in un array reale?
xela84,

19

La classListproprietà garantisce che le classi duplicate non vengano aggiunte inutilmente all'elemento. Al fine di mantenere questa funzionalità, se non ti piace la versione longhand o versione jQuery, suggerirei aggiungendo una addManyfunzione ed removeManyalla DOMTokenList(il tipo di 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]);
    }
}

Questi sarebbero quindi utilizzabili in questo modo:

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

Aggiornare

Secondo i tuoi commenti, se desideri scrivere un metodo personalizzato solo se questi non sono definiti, prova quanto segue:

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

Ancora una buona risposta. E non ho potuto modificarlo per te poiché era composto solo da 2 caratteri.
Pete,

18

Dal momento che il add()metodo dal classListappena permette di passare argomenti separati e non un singolo array, è necessario invocare add()usando applicare. Per il primo argomento dovrai passare il classListriferimento dallo stesso nodo DOM e come secondo argomento l'array di classi che desideri aggiungere:

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

È la versione ES5 della soluzione con Spread Operator (vedi risposta @morkro ). Controllalo facilmente su Babel Repl .
Nickensoul,

7

Per aggiungere classe a un elemento

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

AGGIORNARE:

Rimuovi una classe

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

Questo è interessante da sapere, ma tutto ciò che serve è modificare la stringa della classe. Non funzionerebbe se volessi rimuovere diverse classi. Scusa, ho dimenticato di aggiungerlo nell'OP.
Tenda Enrique Moreno,

4
Da NON usare className. È terribile per le prestazioni (anche il recupero del suo valore provoca un riflusso).
Jacob,

7

Le versioni più recenti delle specifiche DOMTokenList consentono più argomenti add()e remove(), oltre a un secondo argomento, toggle()per forzare lo stato.

Al momento in cui scrivo, Chrome supporta più argomenti su add()e remove(), ma nessuno degli altri browser lo fa. IE 10 e versioni precedenti, Firefox 23 e versioni precedenti, Chrome 23 e versioni precedenti e altri browser non supportano il secondo argomento toggle().

Ho scritto il seguente piccolo polyfill per risolvermi fino a quando il supporto non si espande:

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

DOMTokenListSono previsti un browser moderno con conformità ES5 , ma sto usando questo polyfill in diversi ambienti specificamente mirati, quindi funziona benissimo per me, ma potrebbe essere necessario modificare gli script che verranno eseguiti in ambienti browser legacy come IE 8 e precedenti .


1
Nessuno sembra menzionare che IE10 non consente l'aggiunta di più classi. Questo ha funzionato bene per me, quindi grazie! Vorrei avvertire che in IE9 viene visualizzato un errore per cui DomTokenList non è definito. Potresti voler spiegare anche quello. O eseguilo solo se (typeof DomTokenList! == 'undefined')
Ryan Ore

@Ryan: grazie, pensavo che DOMTokenList fosse supportato in IE 9, ma immagino che sia mancato. Proverò a indagare su una soluzione alternativa ad un certo punto.
Andy E

Sembra che su una DOMTokenList fallita dovresti usare className con controlli al limite di parola regEx
Greg

7

Puoi fare come di seguito

Inserisci

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

Rimuovere

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

Riferimento

TLDR;

In questo caso, la rimozione sopra dovrebbe funzionare. Ma in caso di rimozione, è necessario assicurarsi che la classe esista prima di rimuoverli

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

5

Ecco una soluzione per gli utenti di IE 10 e 11 che sembrava piuttosto semplice.

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

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

O

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
Bella idea Userei .forEach () invece di .map () però - è più pulito / più efficiente per situazioni come questa in cui non si utilizza l'array restituito.
tenni,

Sì è vero.
colecmc,

2

La definizione standard consente solo di aggiungere o eliminare una singola classe. Un paio di piccole funzioni wrapper possono fare ciò che chiedi:

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

Questi wrapper consentono di specificare l'elenco di classi come argomenti separati, come stringhe con spazio o elementi separati da virgola o una combinazione. Per un esempio, vedere http://jsfiddle.net/jstoolsmith/eCqy7


2

Una soluzione molto semplice, non elegante, ma funzionante che dovrei credere è molto cross-browser:

Crea questa funzione

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

Chiamalo così: removeAddClasses (node.classList, arrayToRemove, arrayToAdd);

... dove arrayToRemove è un array di nomi di classi da rimuovere: ['myClass1', 'myClass2'] eccetera

... e arrayToAdd è un array di nomi di classi da aggiungere: ['myClass3', 'myClass4'] eccetera


1

Supponiamo di avere una matrice di classi da aggiungere, è possibile utilizzare la sintassi di diffusione ES6:

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


0

Mi è piaciuta la risposta di @ rich.kelly, ma volevo usare la stessa nomenclatura di classList.add()(stringhe separate da virgola), quindi una leggera deviazione.

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

Quindi puoi quindi usare:

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

Devo testare tutti i browser, ma questo ha funzionato per Chrome.
Dovremmo verificare qualcosa di più specifico dell'esistenza di DOMTokenList.prototype.addMany? Cosa causa esattamente classList.add()l'errore in IE11?


0

Un altro polyfill per element.classListè qui . L'ho trovato tramite MDN .

Includo quello script e uso element.classList.add("first","second","third")come previsto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.