jQuery removeClass通配符

413

有没有一种简单的方法可以删除所有匹配的类,比如

color-*

所以,如果我有一个元素:

<div id="hello" class="color-red color-brown foo bar"></div>

去掉后,它将会是

<div id="hello" class="foo bar"></div>
感谢!

1
一个像“被接受的答案”中的正则表达式会在非空格单词边界处中断。我在下面发布了另一种解决方案。还可以参见:https://dev59.com/GnVD5IYBdhLWcg3wL4mM - Kabir Sarin
@KabirSarin 接受的答案已经更新以解决此问题。 - Emile Bergeron
CSS通配符 http://www.surfingsuccess.com/css/css-wildcard-css-attribute-selector.html#.WHYitbZ95rE - ChatGPT
18个回答

747

4
我认为值得注意的是,这将捕获不从开头开始的匹配类的前导空格。 JavaScript 不支持正向后瞻,因此您需要使用捕获组解决问题。然而这是无意义的,因为 removeClass 函数会通过 classes = ( value || "" ).match( rnotwhite ) || []; 从您的类字符串中删除空格。 - eephillip
1
我最喜欢这个解决方案!我该如何检查是否删除了两个或更多个类?例如 sport-nav-color- - lowtechsun
你会如何匹配以 *-color 结尾的类? - Circle B
5
你可以像这样在你的正则表达式中添加 (color-|sport-|nav-). 它将匹配 color-sport-nav-. 因此,上面的答案将变为 /(^|\s)(color-|sport-|nav-)\S+/g - Bogie
3
接受的答案是正确的,但习惯上我会使用\b来匹配任何单词边界,而不是更繁琐的(^|\s)。因此,例如,要删除由单词magic和非负整数组成的所有类,我会匹配/\bmagic\d+\b/。 - CarlEdman
你如何将一个变量传递给语句?var myVar="color-"; return (className.match (/(^|\s)"+myVar+"S+/g) || []).join(' '); 这样做不起作用! - Tom Senner

106
$('div').attr('class', function(i, c){
    return c.replace(/(^|\s)color-\S+/g, '');
});

5
我喜欢这个,因为它减少了开销并直接进入重点。当attr更好地完成工作时,为什么要使用remove class? - Angry Dan
2
我认为您需要防止空类(c未定义)?至少当我在此页面上尝试下面的插件时,$('a').stripClass('post', 1)会抛出“TypeError: Cannot call method 'replace' of undefined”。链接 - drzaus
1
@Kobi,是的,我认为不可能根据属性进行过滤并返回没有该属性的结果--$('div [class]')应该仅返回具有class的元素,无论它们是否具有值。测试场景:http://jsfiddle.net/drzaus/m83mv/ - drzaus
1
@Kobi - 我想我明白你的意思了;在像.removeProp('class').className=undefined这样的边缘情况中,过滤器[class]仍然返回一些东西,只是它们是undefined。 因此,从技术上讲,它仍然有一个类(与.removeAttr('class')相反),这就是为什么它会破坏你的函数但不会破坏我的变体的原因。 http://jsfiddle.net/drzaus/m83mv/4/ - drzaus
2
添加一个快速测试对我来说很有效:return c && c.replace(/\bcolor-\S+/g, ''); - ssmith
显示剩余2条评论

55

我编写了一个名为alterClass的插件,可以使用通配符匹配方式移除元素类。还可以选择添加类:https://gist.github.com/1517285

$( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' )

1
确实非常好...帮助我重用了一些代码,我只需要删除Twitter Boostrap类,就像这样:$(".search div").children('div').alterClass('span* row-fluid'); - Leniel Maccaferri

18

如果您想在其他地方使用它,我建议您使用一个扩展程序。这个扩展对我来说运作良好。

 $.fn.removeClassStartingWith = function (filter) {
    $(this).removeClass(function (index, className) {
        return (className.match(new RegExp("\\S*" + filter + "\\S*", 'g')) || []).join(' ')
    });
    return this;
};

使用方法:

$(".myClass").removeClassStartingWith('color');

我喜欢jQuery扩展的方法。谢谢! - AFract

17
我已将其概括为一个接受正则表达式作为参数的Jquery插件。
咖啡:
$.fn.removeClassRegex = (regex) ->
  $(@).removeClass (index, classes) ->
    classes.split(/\s+/).filter (c) ->
      regex.test c
    .join ' '

Javascript:


JavaScript(简称JS):是一种高级编程语言,通常用于在Web页面上添加交互式效果和动态内容。它是一种基于对象和事件驱动的语言,并且广泛用于客户端脚本、服务器端编程和桌面应用程序开发。
$.fn.removeClassRegex = function(regex) {
  return $(this).removeClass(function(index, classes) {
    return classes.split(/\s+/).filter(function(c) {
      return regex.test(c);
    }).join(' ');
  });
};

所以,在这种情况下,使用方式将是(无论是在Coffee还是Javascript中):

$('#hello').removeClassRegex(/^color-/)

请注意,我正在使用 Array.filter 函数,该函数在 IE<9 中不存在。您可以使用 Underscore 的 filter 函数 或者搜索类似于 这个 WTFPL 的 polyfill。


5
尝试使用jQuery插件,可以按照以下步骤操作:
$.fn.removeClassLike = function(name) {
    return this.removeClass(function(index, css) {
        return (css.match(new RegExp('\\b(' + name + '\\S*)\\b', 'g')) || []).join(' ');
    });
};

或者这个

$.fn.removeClassLike = function(name) {
    var classes = this.attr('class');
    if (classes) {
        classes = classes.replace(new RegExp('\\b' + name + '\\S*\\s?', 'g'), '').trim();
        classes ? this.attr('class', classes) : this.removeAttr('class');
    }
    return this;
};

编辑:第二种方法应该会更快一些,因为它只在整个类字符串上运行一个正则表达式替换。第一种(较短的)使用jQuery自己的removeClass方法,该方法遍历所有现有的类名并逐一测试它们是否符合给定的正则表达式,因此在内部执行相同的任务时需要更多步骤。然而,在实际使用中,差异是微不足道的。

速度比较基准


为什么有两个选项?哪个更好?各自的优缺点是什么?顺便说一句,我最喜欢你的答案,但它可能需要一些澄清。 - Todd Horst
@ToddHorst 谢谢,我已经更新了答案。实际上,区别只在于更短的代码和更好的性能。 - szegheo

5

一个通用的函数,用于删除任何以begin开头的类:

function removeClassStartingWith(node, begin) {
    node.removeClass (function (index, className) {
        return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
    });
}

http://jsfiddle.net/xa9xS/2900/

var begin = 'color-';

function removeClassStartingWith(node, begin) {
    node.removeClass (function (index, className) {
        return (className.match ( new RegExp("\\b"+begin+"\\S+", "g") ) || []).join(' ');
    });
}

removeClassStartingWith($('#hello'), 'color-');

console.log($("#hello")[0].className);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hello" class="color-red color-brown foo bar"></div>


4
与 @tremby 的答案类似,这里是 @Kobi 的答案作为一个匹配前缀或后缀的插件。
  • 示例:当 stripClass("btn-") 时,去掉 btn-minibtn-danger,但不去掉 btn
  • 示例:当 stripClass('btn', 1) 时,去掉 horsebtncowbtn,但不去掉 btn-minibtn

代码:

$.fn.stripClass = function (partialMatch, endOrBegin) {
    /// <summary>
    /// The way removeClass should have been implemented -- accepts a partialMatch (like "btn-") to search on and remove
    /// </summary>
    /// <param name="partialMatch">the class partial to match against, like "btn-" to match "btn-danger btn-active" but not "btn"</param>
    /// <param name="endOrBegin">omit for beginning match; provide a 'truthy' value to only find classes ending with match</param>
    /// <returns type=""></returns>
    var x = new RegExp((!endOrBegin ? "\\b" : "\\S+") + partialMatch + "\\S*", 'g');

    // https://dev59.com/63E85IYBdhLWcg3wtV71#2644364
    this.attr('class', function (i, c) {
        if (!c) return; // protect against no class
        return c.replace(x, '');
    });
    return this;
};

https://gist.github.com/zaus/6734731


1
就记录而言,我不同意这更简单。 - tremby
@tremby 不好意思,我的意思是在_典型的_使用中更简单(即前缀和后缀),因为你不必每次都写一个正则表达式。 - drzaus
3
我仍然不同意。使用你的方法需要阅读文档并记住endOrBegin值需要是什么,这并不十分直观。写一个正则表达式有什么难的呢?/^match-at-start//match-at-end$/ 已经为所有的JS开发者所熟知了。但各人有各人的喜好。 - tremby
1
@tremby 除了正则表达式容易被滥用,一个不使用正则表达式的方案更接近现有的addClassremoveClasstoggleClass的函数签名,这些函数是每个jQuery开发者都熟知的。阅读文档有什么难的呢? ;) - drzaus
2
阅读文档并不难,但正如@tremby所说,他的解决方案是自我解释的,而你的则需要文档说明。自我解释的解决方案从定义上来说更容易使用。 - hodgef

4

我们可以通过 .attr("class") 获取所有的类,然后转换为数组,进行循环和筛选:

var classArr = $("#sample").attr("class").split(" ")
$("#sample").attr("class", "")
for(var i = 0; i < classArr.length; i ++) {
    // some condition/filter
    if(classArr[i].substr(0, 5) != "color") {
        $("#sample").addClass(classArr[i]);
    }
}

demo: http://jsfiddle.net/L2A27/1/


添加了var prefix='color';并更改了... if (classArr[i].substr(0, prefix.length) != prefix) - Rich C

4

另一种解决这个问题的方法是使用数据属性,它们本质上是唯一的。

您可以这样设置元素的颜色:$el.attr('data-color','red');

然后您可以这样在CSS中设置样式:[data-color="red"]{ color: tomato; }

这就避免了使用类的需要,因为它会带来需要删除旧类的副作用。


1
美观整洁 - eballeste

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