มีวิธีการเพิ่ม / ลบหลายคลาสในหนึ่งคำสั่งเดียวกับ 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
และถ้าคุณต้องการใช้ Array ของหลายชื่อคลาสคุณต้องโทร: DOMTokenList.prototype.add.apply (elem.classList, ['แรก', 'สอง', 'สาม']);
Emanuel Kluge

8
Firefox ไม่รองรับในขณะที่เขียน คำตอบของฉันให้ polyfill
Andy E

ฉันเปลี่ยนมาใช้คำตอบที่ถูกต้องเพราะนี่เป็น API ดั้งเดิมแม้ว่าการสนับสนุนจะไม่ดี
Enrique Moreno Tent

1
คุณได้พิจารณา el.className + = "ชั้นเรียนของฉันที่นี่"
Michael Tontchev

1
มีวิธีลบหลายคลาสหรือไม่
MeVimalkumar

72

ตัวดำเนินการสเปรดใหม่ทำให้ง่ายขึ้นในการใช้คลาส CSS หลายคลาสเป็นอาร์เรย์

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

1
คำตอบที่ยอมรับนั้นใช้ได้กับรายการค่าโดยตรง แต่อันนี้ใช้ได้กับอาร์เรย์ ... ทั้งคู่ดูเหมือนคำตอบที่ยอดเยี่ยม!
Enrique Moreno Tent

ฉันสามารถใช้DOMTokenListอาร์เรย์แทนได้หรือไม่ ฉันรู้ว่า DOMTokenList เป็นวัตถุคล้ายอาร์เรย์ ดังนั้นจึงเป็นไปได้ที่จะใช้มันด้วยclassList.add()วิธีการหรือจะต้องแปลง DOMTokenList เป็นอาร์เรย์จริง?
xela84

19

classListความมั่นใจว่าทรัพย์สินที่เรียนซ้ำกันจะไม่ได้เพิ่มโดยไม่จำเป็นที่จะองค์ประกอบ เพื่อที่จะคงฟังก์ชันการทำงานนี้ไว้หากคุณไม่ชอบรุ่น Longhand หรือ 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 ตัวอักษร
Pete

18

เนื่องจากadd()เมธอดจากclassListjust อนุญาตให้ส่งผ่านอาร์กิวเมนต์ที่แยกกันและไม่ใช่อาร์เรย์เดียวคุณจึงต้องadd()ใช้invoque สำหรับอาร์กิวเมนต์แรกคุณจะต้องผ่านการclassListอ้างอิงจากโหนด DOM เดียวกันและเป็นอาร์กิวเมนต์ที่สองอาร์เรย์ของคลาสที่คุณต้องการเพิ่ม:

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

เป็นโซลูชันรุ่น ES5 พร้อมตัวดำเนินการสเปรด (ดูคำตอบ @morkro ) ตรวจสอบได้ง่ายที่บาเบล Repl
Nickensoul

7

เพื่อเพิ่มคลาสให้กับองค์ประกอบ

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

UPDATE:

ลบชั้นเรียน

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

สิ่งนี้น่าสนใจที่จะรู้ แต่ทั้งหมดก็คือการแก้ไขสตริงของคลาส มันจะไม่ทำงานถ้าฉันต้องการลบหลายคลาส ขออภัยฉันลืมเพิ่มไว้ใน OP
Enrique Moreno Tent

4
อย่าไม่classNameใช้ มันยอดเยี่ยมสำหรับประสิทธิภาพ
jacob

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คาดว่าจะใช้งานได้ แต่ฉันใช้ polyfill นี้ในสภาพแวดล้อมที่มีการกำหนดเป้าหมายเฉพาะหลายอย่างดังนั้นมันจึงใช้งานได้ดีสำหรับฉัน .


1
ดูเหมือนว่าไม่มีใครพูดถึงว่า IE10 ไม่อนุญาตให้เพิ่มหลายคลาส มันใช้งานได้ดีสำหรับฉันขอบคุณมาก! ฉันจะระมัดระวังว่าใน IE9 ฉันได้รับข้อผิดพลาดที่ไม่ได้กำหนด DomTokenList คุณอาจต้องการบัญชีสำหรับสิ่งนั้นด้วย หรือเรียกใช้สิ่งนี้เฉพาะถ้า (typeof DomTokenList! == 'undefined')
Ryan Ore

@ Ryan: ขอบคุณฉันคิดว่า DOMTokenList รองรับใน IE 9 แต่ฉันคิดว่ามันพลาดไป ฉันจะพยายามตรวจสอบวิธีแก้ปัญหาในบางจุด
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

ใช่มันเป็นเรื่องจริง
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]);
  }
}

wrappers เหล่านี้อนุญาตให้คุณระบุรายการของคลาสเป็นอาร์กิวเมนต์ที่แยกต่างหากเช่นสตริงที่มีช่องว่างหรือรายการที่คั่นด้วยเครื่องหมายจุลภาคหรือชุดค่าผสม ดูตัวอย่างได้ที่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

polyfill อีกelement.classListคือที่นี่ ผมพบว่ามันผ่านMDN

ฉันรวมสคริปต์นั้นไว้และใช้งานelement.classList.add("first","second","third")ตามที่ตั้งใจไว้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.