有没有办法用classList在一条指令中添加/删除几个类?

时间:2012-06-20 08:54:29

标签: javascript html5

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

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

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

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

我想知道是否有任何本地方式可以添加或删除。

16 个答案:

答案 0 :(得分:214)

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

相等

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

答案 1 :(得分:46)

新的spread operator使得将多个CSS类应用为数组变得更加容易:

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

答案 2 :(得分:18)

classList属性可确保不会不必要地将重复的类添加到元素中。为了保留此功能,如果您不喜欢速记版本或jQuery版本,我建议您将addMany函数和removeMany添加到DOMTokenListclassList的类型):

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) {...}

答案 3 :(得分:13)

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

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

答案 4 :(得分:11)

您可以像下面这样

添加

Sub Sample()
    Dim lb As OLEObject
    Dim ws As Worksheet

    Set ws = Sheet1

    For Each lb In ws.OLEObjects
        lb.Delete
    Next lb

    Set lb = ws.OLEObjects.Add(ClassType:="Forms.ListBox.1", _
                               Top:=60, _
                               Left:=10, _
                               Height:=100, _
                               Width:=100)

    With lb
        .ListFillRange = "'" & ws.Name & "'!A1:A16" '<~~ Change range here
        '.Object.List = Array("Header", "Value 1", "Value 2", "Value 3")
        .Object.ColumnHeads = True
        .Object.BorderStyle = MSForms.fmBorderStyle.fmBorderStyleSingle
    End With
End Sub

删除

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

Reference

TLDR;

在直接的情况下,上述移除应该有效。但是,如果将其删除,则应确保在删除它们之前存在该类

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

答案 5 :(得分:7)

DOMTokenList spec的较新版本允许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的现代浏览器,但我在几个特定目标环境中使用此polyfill,因此它对我很有用,但可能需要调整将在遗留下运行的脚本浏览器环境,如IE 8及更低版本。

答案 6 :(得分:6)

将类添加到元素

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

更新:

删除课程

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

答案 7 :(得分:4)

这是IE 10和11用户的解决方案,看起来非常简单。

&#13;
&#13;
var elem = document.getElementById('elem');

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

或者

&#13;
&#13;
var elem = document.getElementById('elem'),
    classes = ['first','second','third'];

classes.map(function(item) {
    return elem.classList.add(item);
});
&#13;
<div id="elem">Hello World!</div>
&#13;
&#13;
&#13;

答案 8 :(得分: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

答案 9 :(得分:1)

添加多个由空格分隔的多个类的更好方法是将Spread_syntaxsplit配合使用:

element.classList.add(...classesStr.split(" "));

答案 10 :(得分: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中失败?

答案 11 :(得分:0)

element.classList的另一个polyfill是here。我是通过MDN找到的。

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

答案 12 :(得分:0)

假设您要添加一组类,可以使用ES6扩展语法:

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

答案 13 :(得分:0)

我必须要相信的一个非常简单,不花哨但可行的解决方案是跨浏览器:

创建此功能

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']等

答案 14 :(得分:0)

我发现了一种非常简单的方法,它是一种现代而优雅的方法。


const el = document.querySelector('.m-element');

// To toggle
['class1', 'class2'].map((e) => el.classList.toggle(e));

// To add
['class1', 'class2'].map((e) => el.classList.add(e));

// To remove
['class1', 'class2'].map((e) => el.classList.remove(e));

好的是,您可以扩展类数组或轻松使用任何来自API的内容。

答案 15 :(得分:0)

最佳解决方案之一是检查元素是否存在,然后继续添加或可能删除,最重要的是如果元素为空删除它。

/**
 * @description detect if obj is an element
 * @param {*} obj
 * @returns {Boolean}
 * @example
 * see below
 */
function isElement(obj) {
  if (typeof obj !== 'object') {
    return false
  }
  let prototypeStr, prototype
  do {
    prototype = Object.getPrototypeOf(obj)
    // to work in iframe
    prototypeStr = Object.prototype.toString.call(prototype)
    // '[object Document]' is used to detect document
    if (
      prototypeStr === '[object Element]' ||
      prototypeStr === '[object Document]'
    ) {
      return true
    }
    obj = prototype
    // null is the terminal of object
  } while (prototype !== null)
    return false
}

/*
 * Add multiple class
 * addClasses(element,['class1','class2','class3'])
 * el: element | document.querySelector(".mydiv");
 * classes: passing:: array or string : [] | 'cl1,cl2' | 'cl1 cl2' | 'cl1|cl2'
 */
function addClasses(el, classes) {
  classes = Array.prototype.slice.call(arguments, 1);
  if ( isElement(el) ){ //if (document.body.contains(el)
    for (var i = classes.length; i--;) {
      classes[i] = Array.isArray(classes[i]) ? classes[i]: classes[i].trim().split(/\s*,\s*|\s+/);
      for (var j = classes[i].length; j--;)
        el.classList.add(classes[i][j]);
    }
  }
}

/*
 * Remove multiple class
 * Remove attribute class is empty
 * addClasses(element,['class1','class2','class3'])
 * el: element | document.querySelector(".mydiv");
 * classes: passing:: array or string : [] | 'cl1,cl2' | 'cl1 cl2' | 'cl1|cl2'
 */
function removeClasses(el, classes) {
  classes = Array.prototype.slice.call(arguments, 1);
  if ( isElement(el) ) {
    for (var i = classes.length; i--;) {
      classes[i] = Array.isArray(classes[i]) ? classes[i]: classes[i].trim().split(/\s*,\s*|\s+/);
      for (var j = classes[i].length; j--;)
        el.classList.remove(classes[i][j]);
        let cl = el.className.trim();
        if (!cl){
          el.removeAttribute('class');
        }
    }
  }
}

var div = document.createElement("div");
div.id = 'test'; // div.setAttribute("id", "test");
div.textContent = 'The World';
//div.className = 'class';
// possible use: afterend, beforeend
document.body.insertAdjacentElement('beforeend', div); 

// Everything written above you can do so:
//document.body.insertAdjacentHTML('beforeend', '<div id="text"></div>');

var el = document.querySelector("#test");
addClasses(el,'one,two,three,four');
removeClasses(el,'two,two,never,other');
el.innerHTML = 'I found: '+el.className;
// return : I found: four three one
#test {
  display: inline-block;
  border: 1px solid silver;
  padding: 10px;
}