jQuery removeClass通配符


370

是否有任何简单的方法来删除所有匹配的类,例如,

color-*

所以如果我有一个元素:

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

删除后,它将是

<div id="hello" class="foo bar"></div>

谢谢!


1
像“接受的答案”中一样的正则表达式将在非空间字边界上中断。我在下面发布了替代解决方案。另请参阅:stackoverflow.com/questions/57812/...
sarink

@KabirSarin接受的答案已经更新以解决此问题。
Emile Bergeron

Answers:


679

jQuery 1.4开始removeClass函数接受一个函数参数。

$("#hello").removeClass (function (index, className) {
    return (className.match (/(^|\s)color-\S+/g) || []).join(' ');
});

实时示例:http//jsfiddle.net/xa9xS/1409/


4
我认为值得一提的是,这将捕获一个匹配的类的领先空白,这些空白并不是从一开始就开始的。Javascript不支持正向回溯,因此您必须使用捕获组解决方法。但是,这是有争议的,因为removeClass函数将通过classes = ( value || "" ).match( rnotwhite ) || [];
eephillip

我最喜欢这个解决方案!如何检查要删除的两个或多个类?即sport-nav-color-
lowtechsun '16

您将如何匹配类末尾的类*-color
圈B

3
@lowtechsun,您可以像这样在您的正则表达式中添加(color-|sport-|nav-)。它将与color-sport-或匹配nav-。因此,以上答案将变为/(^|\s)(color-|sport-|nav-)\S+/g
转向架

1
可接受的答案是正确的,但是习惯上,我会使用\ b在任何单词边界上匹配,而不是比较罗word的(^ | \ s)。因此,例如,要删除所有由单词magic组成的类,后跟一个非负整数并且只有那些,我将在/ \ bmagic \ d + \ b /上进行匹配。
CarlEdman '16

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

5
我喜欢这样做,因为它可以减少开销,并直达重点。为什么在attr做的更好的情况下使用remove class?
生气的丹

2
我认为您需要防止空类(c is undefined)?至少当我在此页面上的插件中尝试以下操作时$('a').stripClass('post', 1)抛出“ TypeError:无法调用未定义的方法'replace'”
drzaus 2013年

1
@Kobi是的,我认为不可能对属性进行过滤并返回没有属性的结果- $('div[class]')应该仅返回带有的元素class,无论它们是否具有值。测试方案:jsfiddle.net/drzaus/m83mv
drzaus 2013年

1
@Kobi-我想我明白你的意思了;在诸如.removeProp('class').className=undefined过滤器[class]仍返回某些内容的情况下,它们只是undefined。因此从技术上讲,它仍然具有一个类(与相对.removeAttr('class'),这就是为什么它破坏了您的功能但没有我的变体的 原因。jsfiddle.net
drzaus/

1
添加快速测试对我return c && c.replace(/\bcolor-\S+/g, '');
有用

50

我编写了一个名为alterClass的插件-删除具有通配符匹配的元素类。(可选)添加类:https : //gist.github.com/1517285

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

1
确实非常好……帮助我重用了一些我只需要删除以下Twitter Boostrap类的代码:$(".search div").children('div').alterClass('span* row-fluid');
Leniel Maccaferri 2013年

15

我已经将其概括为一个使用正则表达式作为参数的Jquery插件。

咖啡:

$.fn.removeClassRegex = (regex) ->
  $(@).removeClass (index, classes) ->
    classes.split(/\s+/).filter (c) ->
      regex.test c
    .join ' '

Javascript:

$.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的过滤器功能,也可以使用Google进行类似WTFPL这样的polyfill


11

如果您想在其他地方使用它,我建议您扩展。这对我来说很好。

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

用法:

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

4

我们可以通过获取所有类.attr("class"),并获取Array,And和loop&filter:

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]);
    }
}

演示:http : //jsfiddle.net/L2A27/1/


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

4

到@ tremby的类似的答案,这里是@了Kobi的答案作为一个插件,将匹配前缀或后缀。

  • EX)条btn-minibtn-danger而不btnstripClass("btn-")
  • 例如)带horsebtncowbtn但不带btn-minibtn何时stripClass('btn', 1)

码:

$.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://stackoverflow.com/a/2644364/1037948
    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 2014年

@tremby抱歉,我的意思是简化典型用法(即前缀和后缀),因为您不必每次都编写正则表达式
drzaus 2014年

3
我仍然不同意。使用您的方法,您必须阅读文档并记住确切的值是什么endOrBegin。这不是不言自明的。编写正则表达式有什么困难?/^match-at-start/并且/match-at-end$/每个JS开发人员都知道。但是每个人都有自己的。
2014年

1
@tremby除了正则表达式乞讨被滥用,非正则表达式选项的现有签名更紧密地相匹配addClassremoveClasstoggleClass,这是众所周知的每一个jQuery的开发者。阅读文档有什么困难?;)
drzaus

2
阅读文档没有什么困难,但是正如@tremby所说,他的解决方案是不言自明的,而您的解决方案则需要文档。不言而喻的解决方案根据定义更易于使用。
Francisco Hodge,

2

对于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;
};

2

根据ARS81回答(仅匹配以开头的类名),这是一个更灵活的版本。也是hasClass()正则表达式版本。

用法: $('.selector').removeClassRegex('\\S*-foo[0-9]+')

$.fn.removeClassRegex = function(name) {
  return this.removeClass(function(index, css) {
    return (css.match(new RegExp('\\b(' + name + ')\\b', 'g')) || []).join(' ');
  });
};

$.fn.hasClassRegex = function(name) {
  return this.attr('class').match(new RegExp('\\b(' + name + ')\\b', 'g')) !== null;
};

2

这将有效地删除所有prefix从节点class属性开始的类名。其他答案不支持SVG元素(在撰写本文时),但是此解决方案支持:

$.fn.removeClassPrefix = function(prefix){
    var c, regex = new RegExp("(^|\\s)" + prefix + "\\S+", 'g');
    return this.each(function(){
        c = this.getAttribute('class');
        this.setAttribute('class', c.replace(regex, ''));
    });
};

RegExp在每个回调中创建一次对象不是更有效吗?
Emile Bergeron

1
@EmileBergeron-是的!我将进行更改
vsync

2

我遇到了同样的问题,并提出了以下使用下划线的_.filter方法的问题。一旦我发现removeClass带有一个函数并为您提供了一个类名列表,就很容易将其转换为数组并过滤掉类名以返回到removeClass方法。

// Wildcard removeClass on 'color-*'
$('[class^="color-"]').removeClass (function (index, classes) {
  var
    classesArray = classes.split(' '),
    removeClass = _.filter(classesArray, function(className){ return className.indexOf('color-') === 0; }).toString();

  return removeClass;
});

1
你能解释一下下划线在做什么_.filter
巴特

2

您也可以使用Element.classList使用香草JavaScript进行此操作。也无需使用正则表达式:

function removeColorClasses(element) { for (let className of Array.from(element.classList)) if (className.startsWith("color-")) element.classList.remove(className); }

注意:请注意,我们在开始之前创建了一个Array副本classList,这一点很重要,因为这classList是一个实时DomTokenList版本,随着类的删除而更新。


1

您还可以使用className元素的DOM对象的属性:

var $hello = $('#hello');
$('#hello').attr('class', $hello.get(0).className.replace(/\bcolor-\S+/g, ''));

1

泛型函数,用于删除任何以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>


0

在单词边界上进行正则表达式分割\b不是解决此问题的最佳方法:

var prefix = "prefix";
var classes = el.className.split(" ").filter(function(c) {
    return c.lastIndexOf(prefix, 0) !== 0;
});
el.className = classes.join(" ");

或作为jQuery mixin:

$.fn.removeClassPrefix = function(prefix) {
    this.each(function(i, el) {
        var classes = el.className.split(" ").filter(function(c) {
            return c.lastIndexOf(prefix, 0) !== 0;
        });
        el.className = classes.join(" ");
    });
    return this;
};

0

如果您有多个具有类名“ example”的元素,则要在所有元素中都删除“ color-”类,可以执行以下操作:[使用jquery]

var objs = $('html').find('.example');
for(index=0 ; index < obj1s.length ; index++){
    objs[index].className = objs[index].className.replace(/col-[a-z1-9\-]*/,'');
}

如果您不在正则表达式中添加[a-z1-9-] *,则不会删除名称中带有数字或某些“-”的类。


0

如果您只需要删除最后设置的颜色,则可能需要以下设置。

在我的情况下,我需要在click事件中向body标签添加颜色类,并删除最后设置的颜色。在这种情况下,您将存储当前颜色,然后查找数据标签以删除最后设置的颜色。

码:

var colorID = 'Whatever your new color is';

var bodyTag = $('body');
var prevColor = bodyTag.data('currentColor'); // get current color
bodyTag.removeClass(prevColor);
bodyTag.addClass(colorID);
bodyTag.data('currentColor',colorID); // set the new color as current

可能不完全是您所需要的,但对我而言,这是我所关注的第一个SO问题,因此我想我会分享我的解决方案,以防它对任何人有帮助。


在这里无关紧要。您可能已经回答了自己的问题,因为这是对SO的鼓励行为。
Emile Bergeron,2016年

@Emile:是的。我可能会这样做,因为它没有直接回答原始问题。我应该保留还是删除此答案?
redfox05 '16

那时,这需要您自担风险,尚未对其进行投票或支持。因此,您可以毫无风险地将其移至您自己的问题。另外,请通过检查是否存在问题来避免重复。
Emile Bergeron

0

解决此问题的另一种方法是使用数据属性,该属性本质上是唯一的。

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

您可以在CSS中设置样式,例如: [data-color="red"]{ color: tomato; }

这消除了使用类的需要,而这具有需要删除旧类的副作用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.