Чи є спосіб додати / видалити кілька класів в одній одній інструкції з classList?


164

Поки що я повинен це зробити:

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

Хоча це можна зробити в jQuery, як це

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

Мені хотілося б знати, чи є якийсь рідний спосіб додати чи видалити.

Відповіді:


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

дорівнює

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

15
І якщо ви хочете застосувати масив декількох імен класів, вам потрібно зателефонувати: DOMTokenList.prototype.add.apply (elem.classList, ['first', 'second', '3rd']);
Емануель Клюге

8
Firefox теж не підтримує його під час написання. У моїй відповіді передбачено поліфіл.
Енді Е

Я переходжу на цю як правильну відповідь, оскільки це рідний API, навіть якщо підтримка не велика.
Енріке Морено намет

1
Чи вважали ви el.className + = "мої заняття тут"
Михайло Тончев

1
чи є спосіб видалити кілька класів
MeVimalkumar

72

Новий оператор розповсюдження полегшує застосування декількох класів CSS як масиву:

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

1
Прийнята відповідь працює з прямим списком значень, але ця працює з масивами ... обидва здаються відмінними відповідями!
Енріке Морено намет

Чи можна використовувати DOMTokenListзамість масиву? Я знаю, що DOMTokenList - це об'єкт, схожий на масив. Отже, можна використовувати його classList.add()методом або DOMTokenList повинен бути перетворений в реальний масив?
xela84

19

classListВластивість гарантує , що повторюються класи надмірно не додаються до елементу. Щоб зберегти цю функціональність, якщо вам не подобаються довгострокові версії або версії jQuery, я б запропонував додати addManyфункцію та removeManyдо DOMTokenList(тип 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]);
    }
}

Вони можуть бути корисними так:

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

Оновлення

Відповідно до ваших коментарів, якщо ви хочете написати лише спеціальний метод для них у випадку, якщо вони не визначені, спробуйте наступне:

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

Ще хороша відповідь. І я не зміг її відредагувати, оскільки це було лише 2 символи.
Піт

18

Оскільки add()метод із classListсправедливого дозволяє передавати окремі аргументи, а не один масив, потрібно викликати add()за допомогою Apply. Для першого аргументу вам потрібно буде передати classListпосилання з того ж вузла DOM і як другий аргумент масив класів, який ви хочете додати:

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

Це версія рішення ES5 з оператором Spread (див. Відповідь @morkro ). Перевірте це легко у Babel Repl .
Нікенсул

7

Щоб додати клас до елемента

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

ОНОВЛЕННЯ:

Видаліть клас

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

Це цікаво знати, але все, що він робить, - це редагувати рядок класу. Він би не працював, якщо я хотів видалити кілька класів. Вибачте, я забув додати це в ОП.
Енріке Морено намет

4
Як НЕ використовувати className. Це жахливо для продуктивності (навіть отримання його значення викликає поповнення).
Якоб

7

Новіші версії специфікації DOMTokenList дозволяють отримати безліч аргументів add()і remove(), а також другий аргумент toggle()для примусового стану.

На момент написання, Chrome підтримує кілька аргументів , add()і remove(), але жоден з інших браузерів не роблять. IE 10 і новіші версії, Firefox 23 і новіші версії, Chrome 23 і нижчі та інші браузери не підтримують другий аргумент toggle().

Я написав наступний маленький поліфайл, щоб прислухати мене до тих пір, поки підтримка не розшириться:

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

Сучасний браузер із відповідністю ES5, і DOMTokenListочікується, але я використовую цю полісистему в декількох конкретно орієнтованих середовищах, тому вона чудово працює для мене, але може знадобитися налаштування сценаріїв, які працюватимуть у застарілих середовищах браузера, таких як IE 8 і нижче .


1
Здається, ніхто не згадує, що IE10 не дозволяє додавати кілька класів. Це добре працювало для мене, тому дякую! Я б застеріг, хоча в IE9 я отримую помилку, що DomTokenList не визначено. Можливо, ви також хочете це врахувати. Або запустити це лише у випадку, якщо (наберіть DomTokenList! == 'undefined')
Райан Руд

@Ryan: спасибі, я думав, що DOMTokenList підтримується в IE 9, але, мабуть, це було пропущено. Я спробую дослідити вирішення проблеми в якийсь момент.
Енді Е

Схоже, у невдалому DOMTokenList вам доведеться використовувати className з переходом regEx слова кордону
Грег

7

Ви можете зробити так, як нижче

Додайте

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

Видалити

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

Довідково

TLDR;

У прямому прямому випадку вилучення повинно працювати. Але у випадку видалення, ви повинні переконатися, що існує клас, перш ніж їх видалити

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

5

Ось розробка для користувачів IE 10 та 11, які здалися досить прямими.

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

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

Або

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
Хороша ідея. Я б використовував .forEach () замість .map (), хоча - це чистіше / ефективніше для таких ситуацій, коли ви не використовуєте повернутий масив.
десять

Так, це правда.
colecmc

2

Стандартний дефінітон дозволяє лише додавати або видаляти один клас. Кілька маленьких функцій обгортки можуть робити те, що ви просите:

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

Ці обгортки дозволяють вам вказати список класів як окремі аргументи, як рядки з елементами, розділеними пробілом або комами, або комбінацію. Для прикладу див. Http://jsfiddle.net/jstoolsmith/eCqy7


2

Дуже просте, не фантазійне, але робоче рішення, в яке я б повинен повірити, це дуже крос-браузер:

Створіть цю функцію

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

Назвіть це так: RemoveAddClasses (node.classList, arrayToRemove, arrayToAdd);

... де arrayToRemove - це масив імен класів для видалення: ['myClass1', 'myClass2'] etcetera

... і arrayToAdd - це масив імен класів, які потрібно додати: ['myClass3', 'myClass4'] etcetera


1

Припустимо, що у вас є масив класів для додавання, ви можете використовувати синтаксис поширення ES6:

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


0

Мені сподобалась відповідь @ rich.kelly, але я хотів використати ту саму номенклатуру, що і classList.add()(розділені комами рядки), тому незначне відхилення.

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

Тоді ви можете використовувати:

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

Мені потрібно перевірити всі браузери, але це працювало для Chrome.
Чи слід перевіряти чи щось більш конкретне, ніж існування DOMTokenList.prototype.addMany? Що саме викликає classList.add()збій в IE11?


0

Ще одна полізасипка element.classListє тут . Я знайшов це через MDN .

Я включаю цей сценарій і використовую element.classList.add("first","second","third")за призначенням.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.