有没有一种方法可以使用classList在一条指令中添加/删除多个类?


164

到目前为止,我必须这样做:

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

虽然这在jQuery中是可行的,但是像这样

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

我想知道是否有添加或删除的本机方法。

Answers:


313
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也不支持它。 我的答案提供了一个polyfill。
Andy E

我将其切换为正确答案,因为这是本机API,即使支持程度不高。
Enrique Moreno Tent 2014年

1
您是否考虑过el.className + =“我的课程在这里”
Michael Tontchev

1
有没有一种方法可以删除多个类
MeVimalkumar

72

新的传播运算符使将多个CSS类作为数组应用更加容易:

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

1
可接受的答案适用于值的直接列表,但此答案适用于数组...两者似乎都是极好的答案!
恩里克·莫雷诺

我可以使用DOMTokenList而不是数组吗?我知道DOMTokenList是一个类似数组的对象。因此,有可能使用该classList.add()方法,还是必须将DOMTokenList转换为真实数组?
xela84

19

classList属性确保不必将重复的类不必要地添加到元素中。为了保留此功能,如果您不喜欢普通版本或jQuery版本,建议您添加一个addMany函数并添加removeManyDOMTokenList(的类型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

由于Just中的add()方法classList允许传递单独的参数而不是单个数组,因此您需要add()使用apply 进行调用。对于第一个参数,您将需要传递classList来自同一DOM节点的引用,第二个参数是您要添加的类的数组:

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

它是带有Spread运算符的解决方案的ES5版本(请参阅@morkro 答案)。在Babel Repl轻松检查。
Nickensoul '18年

7

向元素添加类

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

更新:

删除课程

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

知道这很有趣,但是它所做的只是编辑类的字符串。如果我想删除几个类,那就行不通了。抱歉,我忘了在OP中添加它。
Enrique Moreno Tent 2012年

4
千万不要使用className。它对性能很糟糕(即使检索其值也会导致重排)。
jacob

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是可以预期的,但是我在几个特定的​​目标环境中使用此polyfill,因此它对我来说非常有用,但是可能需要调整将在IE 8和更低版本的旧版浏览器环境中运行的脚本。


1
似乎没有人提到IE10不允许添加多个类。这对我来说很好,谢谢!我会警告,尽管在IE9中我收到未定义DomTokenList的错误。您可能也要考虑到这一点。或仅运行此if(typeof DomTokenList!=='undefined')
Ryan Ore

@Ryan:谢谢,我以为IE 9支持DOMTokenList,但我想它被遗漏了。我将尝试研究某个变通办法。
Andy E

看起来在失败的DOMTokenList上,您必须使用className进行单词边界regEx检查
Greg

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()–在这种情况下(您不使用返回的数组)它更干净/更高效。
tenni '18

是的,这是真的。
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']等

...和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

另一个填充工具element.classList在这里。我是通过MDN找到的。

我包括该脚本并按element.classList.add("first","second","third")预期使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.