是否有一种方法可以在使用classList的单个指令中添加/删除多个类?

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

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

这在jQuery中是可以实现的,就像这样

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

我想知道是否有任何本地的方法来添加或删除。

214760 次浏览

向元素中添加类

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

更新:

删除一个类

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

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

标准定义只允许添加或删除单个类。有几个小的包装器函数可以完成您的要求:

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

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

是相等的

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

更新版本的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的现代浏览器是预期的,但我在几个特定的目标环境中使用这个polyfill,所以它对我来说工作得很好,但它可能需要调整脚本,以便在遗留的浏览器环境中运行,如IE 8或更低版本。

我喜欢@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的存在更具体的东西?到底是什么原因导致IE11中classList.add()失败?< / p >

element.classList的另一个填充是在这里。我通过中数找到它。

我包括该脚本,并使用element.classList.add("first","second","third")作为它的意图。

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

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

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

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

假设你有一个要添加的类数组,你可以使用ES6扩展语法:

< p > <代码> Let classes = ['first', 'second', 'third']; elem.classList.add(…类); < /代码> < / p >

下面是一个针对ie10和ie11用户的工作,看起来非常简单。

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


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

Or

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


classes.forEach(function(item) {
elem.classList.add(item);
});
<div id="elem">Hello World!</div>

一个非常简单,不花哨,但有效的解决方案,我不得不相信是非常跨浏览器的:

创建这个函数

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); < / p > < p >…其中arrayToRemove是要删除的类名数组: [' myClass1 ', ' myClass2 ']等等< / p > < p >…and arrayToAdd是一个要添加的类名数组: [' myClass3 ', ' myClass4 ']等等< / p >

你可以像下面这样做

添加

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


// OR


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

删除

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


// OR


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

Reference .

TLDR;

在上述直接的情况下,拆卸应该工作。但是在删除的情况下,应该在删除它们之前确保类存在

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

在字符串中添加以空格分隔的多个类的更好方法是使用Spread_syntax分裂:

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

我发现了一个非常简单的方法,更现代和优雅的方式。


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的类数组。

其中一个最好的解决方案是检查一个元素是否存在,然后继续添加或可能删除,尤其是如果元素为空删除它。

/**
* @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;
}