如何使用纯JavaScript切换元素的类?

174

我正在寻找一种将此jQuery代码(用于响应式菜单部分)转换为纯JavaScript的方法。

如果难以实现,可以使用其他JavaScript框架。

$('.btn-navbar').click(function()
{
    $('.container-fluid:first').toggleClass('menu-hidden');
    $('#menu').toggleClass('hidden-phone');

    if (typeof masonryGallery != 'undefined') 
        masonryGallery();
});

1
https://dev59.com/6HVC5IYBdhLWcg3wvT7g - Johan
14
document.getElementById("menu").classList.toggle("hidden-phone") - Bergi
classList在一些浏览器中不受支持:http://caniuse.com/classlist - Kevin Whitaker
7
嘿 @max,想要选择一个答案了吗? - mikemaccana
2
旁白:Max在接下来的七年里没有选择答案,而Mike并不知道,在写下这句话后不久,他会离婚。 - mikemaccana
13个回答

283

如果我们不能使用ID,那么我们该怎么做呢? - Goku
但是,然后我们将拥有相同的类数量而不是旧的ID,并使用类似var myList = document.getElementsByClassName("abc")这样的东西。 - Goku
1
@goku 类不会出现在 window 对象下面,只有 ID 会。请参见 http://www.2ality.com/2012/08/ids-are-global.html。 - mikemaccana
1
除了第二个参数外,IE10和IE11都支持。 - Below the Radar
1
非常感谢!现在它可以工作了 :) 我为循环添加了更多选项: var All = document.querySelectorAll('.menu'); for (var i = 0; i < All.length; i++){ All[i].classList.toggle('hidden-phone'); } - Blue Tram
@BlueTram 现在你只需要使用 nodeList.forEach() 就可以了。 - mikemaccana

27

这是用ES6实现的解决方案

const toggleClass = (el, className) => el.classList.toggle(className);

用法示例

toggleClass(document.querySelector('div.active'), 'active'); // The div container will not have the 'active' class anymore

4
ES6很好,但是这个解决方案只是使用了“document.querySelector”和“element.classList.toggle”,与其他现有的答案一样。 - mikemaccana
如果一个解决方案是“供应商导向”的,那么它就无效,因为互联网是以开放标准为导向的。 - Peter Krauss
这不是适用于大量文件的解决方案。它在querySelectorAll中无法工作(至少在FF中),因此对于那些想要在多个元素上切换类的人,请继续阅读 :-)(我起初没有继续阅读 - 因此我的评论!) - user9813195

11

看一下这个例子:JS Fiddle

function toggleClass(element, className){
    if (!element || !className){
        return;
    }

    var classString = element.className, nameIndex = classString.indexOf(className);
    if (nameIndex == -1) {
        classString += ' ' + className;
    }
    else {
        classString = classString.substr(0, nameIndex) + classString.substr(nameIndex+className.length);
    }
    element.className = classString;
}

11
如果我在“红色”之后有一个名为“redOther”的类,会怎样? - JJPP

7
不需要正则表达式,只需使用类列表(classlist)。

var id=document.getElementById('myButton');


function toggle(el,classname){
if(el.classList.contains(classname)){
el.classList.remove(classname)
}
else{
el.classList.add(classname)
}
}




id.addEventListener('click',(e)=>{

toggle(e.target,'red')
})
.red{

background:red

}
<button id="myButton">Switch</button>

以上示例的简单用法

var id=document.getElementById('myButton');


function toggle(el,classname){
el.classList.toggle(classname)
}




id.addEventListener('click',(e)=>{

toggle(e.target,'red')
})
.red{

background:red

}
<button id="myButton">Switch</button>


4
如果有人想要使用JavaScript在鼠标悬停/移出时切换类,以下是代码:

如果有人想要使用JavaScript在鼠标悬停/移出时切换类,以下是代码

function changeColor() {
    this.classList.toggle('red');
    this.classList.toggle('green');
}

 document.querySelector('#btn').addEventListener('mouseenter', changeColor);
 document.querySelector('#btn').addEventListener('mouseleave', changeColor );

演示Fiddle链接:https://jsfiddle.net/eg2k7mLj/1/

来源:切换类(基于纯Javascript,不使用jQuery)


4
这个代码也适用于早期版本的IE浏览器。

function toogleClass(ele, class1) {
  var classes = ele.className;
  var regex = new RegExp('\\b' + class1 + '\\b');
  var hasOne = classes.match(regex);
  class1 = class1.replace(/\s+/g, '');
  if (hasOne)
    ele.className = classes.replace(regex, '');
  else
    ele.className = classes + class1;
}
.red {
  background-color: red
}
div {
  width: 100px;
  height: 100px;
  margin-bottom: 10px;
  border: 1px solid black;
}
<div class="does red redAnother " onclick="toogleClass(this, 'red')"></div>

<div class="does collapse navbar-collapse " onclick="toogleClass(this, 'red')"></div>


1
\b 单词边界与 CSS 类名分隔符不一致。例如,如果类名包含破折号(“-”)字符,则无法正常工作:btn、btn-red 都将匹配 '\\b' + 'btn' + '\\b' !! - S.Serpooshan

3
这可能更加简明扼要:
function toggle(element, klass) {
  var classes = element.className.match(/\S+/g) || [],
      index = classes.indexOf(klass);

  index >= 0 ? classes.splice(index, 1) : classes.push(klass);
  element.className = classes.join(' ');
}

1

仅出于遗留原因:

function toggleClassName(elementClassName, className) {
    const originalClassNames = elementClassName.split(/\s+/);
    const newClassNames = [];
    let found = false;
    for (let index = 0; index < originalClassNames.length; index++) {
        if (originalClassNames[index] === '') {
            continue;
        }
        if (originalClassNames[index] === className) {
            found = true;
            continue;
        }
        newClassNames.push(originalClassNames[index]);
    }
    if (!found) {
        newClassNames.push(className);
    }

    return newClassNames.join(' ');
}

console.assert(toggleClassName('', 'foo')                        === 'foo');
console.assert(toggleClassName('foo', 'bar')                     === 'foo bar');
console.assert(toggleClassName('foo bar', 'bar')                 === 'foo');
console.assert(toggleClassName('bar foo', 'bar')                 === 'foo');
console.assert(toggleClassName('foo bar baz', 'bar')             === 'foo baz');
console.assert(toggleClassName('foo-bar', 'foo')                 === 'foo-bar foo');
console.assert(toggleClassName('bar foo-bar', 'bar')             === 'foo-bar');
console.assert(toggleClassName('bar bar bar foo-bar bar', 'bar') === 'foo-bar');
console.assert(toggleClassName(" \n\nbar-bar \nbar-baz foo", 'bar-baz') === 'bar-bar foo');

element.className = toggleClassName(element.className, 'foo');

可能不是必要的。但我喜欢这样做也可以通过删除相同类的多个出现来清理类名列表。 - Rob Waa

0
如果你想使用本地解决方案为元素切换类,可以尝试这个建议。我在不同的情况下尝试过它,无论元素上是否有其他类,我认为它都非常有效:
(function(objSelector, objClass){
   document.querySelectorAll(objSelector).forEach(function(o){
      o.addEventListener('click', function(e){
        var $this = e.target,
            klass = $this.className,
            findClass = new RegExp('\\b\\s*' + objClass + '\\S*\\s?', 'g');

        if( !findClass.test( $this.className ) )
            if( klass ) 
                $this.className = klass + ' ' + objClass;
            else 
                $this.setAttribute('class', objClass);
        else 
        {
            klass = klass.replace( findClass, '' );
            if(klass) $this.className = klass;
            else $this.removeAttribute('class');
        }
    });
  });
})('.yourElemetnSelector', 'yourClass');

0

这里是一个针对IE >= 9的代码,使用split(" ")来处理className:

function toggleClass(element, className) {
    var arrayClass = element.className.split(" ");
    var index = arrayClass.indexOf(className);

    if (index === -1) {
        if (element.className !== "") {
            element.className += ' '
        }
        element.className += className;
    } else {
        arrayClass.splice(index, 1);
        element.className = "";
        for (var i = 0; i < arrayClass.length; i++) {
            element.className += arrayClass[i];
            if (i < arrayClass.length - 1) {
                element.className += " ";
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接