Есть ли способ добавить / удалить несколько классов в одной инструкции с classList?


164

Пока я должен сделать это:

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

Хотя это возможно в jQuery, вот так

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

Я хотел бы знать, есть ли какой-либо родной способ добавить или удалить.

Ответы:


315
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', 'third']);
Эмануэль Клюге

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()метод из classListjust позволяет передавать отдельные аргументы, а не один массив, вам нужно вызывать add()с помощью apply. Для первого аргумента вам нужно будет передать classListссылку из того же узла DOM, а в качестве второго аргумента - массив классов, которые вы хотите добавить:

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

Это ES5-версия решения с оператором распространения (см. Ответ @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().

Я написал следующий небольшой polyfill, чтобы прикрыть меня, пока поддержка не расширится:

(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 не определен. Возможно, вы захотите объяснить это тоже. Или только запустить это, если (typeof DomTokenList! == 'undefined')
Райан Руд

@Ryan: спасибо, я думал, что DOMTokenList поддерживается в IE 9, но, думаю, его не было. Я постараюсь найти обходной путь в какой-то момент.
Энди Э

Похоже, что в сбойном DOMTokenList вы должны будете использовать className с проверкой границ регулярного слова
Грег

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'] и так далее


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

Другой polyfill для element.classListэто здесь . Я нашел это через MDN .

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.