JS 删除 class 的方法
给元素加 class 谁都会,删的时候问题就多了:删一个还是删多个?元素有多个 class 时会不会误删?老项目里还要兼容 IE。这里把几种写法都过一遍。
一、classList.remove:现代浏览器首选
const el = document.getElementById('box');
// 删一个
el.classList.remove('active');
// 删多个
el.classList.remove('active', 'show', 'disabled');
classList 是 DOMTokenList 对象,remove 支持一次传多个参数,不存在的 class 不会报错,静默忽略。这个特性比字符串替换安全得多。
classList 的其他方法:
el.classList.add('active'); // 添加
el.classList.toggle('active'); // 有则删,无则加
el.classList.contains('active'); // 是否包含
el.classList.replace('old', 'new');// 替换
注意 classList 的值是只读的集合,不能直接赋值,el.classList = 'xxx' 无效。
二、className:字符串操作
// 直接覆盖,会清掉其他所有 class
el.className = '';
// 保留部分 class
el.className = 'box active';
className 是字符串,赋值会完全替换。想删除其中一个,得自己处理字符串:
el.className = el.className
.split(' ')
.filter(c => c !== 'active')
.join(' ');
麻烦但兼容性最好,IE8 及以下也能跑。注意多个空格会产生空字符串项,filter 时顺手去掉。
三、setAttribute / removeAttribute
el.removeAttribute('class'); // 整个 class 属性删掉
el.setAttribute('class', 'box'); // 重设
removeAttribute('class') 和 el.className = '' 效果差不多,都会让元素没有 class 属性。区别是前者连属性名都移除,后者会留一个空属性。视觉上没差别,但用 CSS 属性选择器 [class] 时行为不同。
四、jQuery 写法
$('#box').removeClass('active');
$('#box').removeClass('active show'); // 空格分隔删多个
$('#box').removeClass(); // 清空所有 class
removeClass 不带参数会清空全部,这点和原生不一样,容易误用。jQuery 3.x 之后内部也是走 classList,性能差不多。
五、几个容易踩的坑
1. 元素不存在
document.querySelector('.not-exist').classList.remove('x');
// TypeError: Cannot read properties of null
先判空再操作,尤其是异步渲染的页面,元素可能还没生成。
2. SVG 元素的 classList
老版本浏览器里 SVG 的 className 是 SVGAnimatedString 对象,不是字符串,直接拼字符串会得到 "[object SVGAnimatedString]"。用 classList 就没这个问题,或者用 getAttribute('class')。
3. 多个元素
// querySelectorAll 返回 NodeList,不能直接调 classList
document.querySelectorAll('.item').forEach(el => {
el.classList.remove('active');
});
NodeList 在旧浏览器里没有 forEach,转数组:Array.prototype.forEach.call(list, fn)。
4. 删除后样式没变
可能是 CSS 里用了更高优先级的选择器,或者 class 名拼错了。也可能是元素上有内联 style 覆盖了 class 的样式,删 class 不影响内联样式。
5. 动画过渡失效
删除 class 触发 transition 时,如果元素刚被插入 DOM 就立刻删,浏览器还没完成首次渲染,过渡不会执行。需要 requestAnimationFrame 或者 setTimeout 延迟一帧。
六、场景示例
切换选中状态
document.querySelectorAll('.tab').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
});
});
先全部清掉,再给当前加,这是最不容易出错的写法。用 toggle 反而会出现多个同时选中。
关闭弹窗
function closeModal() {
const modal = document.querySelector('.modal');
if (!modal) return;
modal.classList.remove('show');
// 等动画结束再隐藏
setTimeout(() => modal.classList.remove('open'), 300);
}
批量清理
// 清掉所有状态类
['active', 'show', 'error', 'loading'].forEach(c => el.classList.remove(c));
比写四行 remove 更简洁,也方便以后加新的状态类。