删除所有以特定字符串开头的类

117

我有一个带有id="a"

,上面可能会有来自多个组的各种类。每个组都有一个特定的前缀。在javascript中,我不知道
上属于哪个组的类。我想能够清除所有具有给定前缀的类,然后添加一个新类。如果我想要删除以“bg”开头的所有类,我该怎么做?类似于这样,但实际上起作用的是什么:

```js $("#a").removeClass(function(index, className) { return (className.match(/\bbg\S+/g) || []).join(' '); }).addClass("newClass"); ```
$("#a").removeClass("bg*");
16个回答

119

在这种情况下,使用单词边界\b进行正则表达式拆分并不是最好的解决方案:

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

或者作为jQuery混合函数:

$.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 = $.trim(classes.join(" "));
    });
    return this;
};

2018年ES6更新:

const prefix = "prefix";
const classes = el.className.split(" ").filter(c => !c.startsWith(prefix));
el.className = classes.join(" ").trim();

10
这种方法比使用带有\b(单词边界检查)的RegExp更好,因为它可以防止“僵尸类”出现。如果你有像“前缀-后缀”这样的类,那么本主题中的“最佳答案”将保留类“-后缀”,因为\b会在“-”字符之前分割。你的split-map-join解决方案可以解决这个问题 :)我基于你的解决方案创建了一个微小的jQuery插件,Kabir:(https://gist.github.com/2881585) - Jakub P.
3
我也同意,其他答案似乎只是简单的正则表达式,会在非空格单词边界处出现错误。如果明天我有时间,我会提供一个单元测试来证明这一点。 - gerges
1
我喜欢它,尽管这实际上不是有效的代码,因为filter中的匿名函数必须返回一个布尔值。这将起作用:`var classes = $(e).attr("class").split(" "); $(classes).each(function(i, item) { classes[i] = item.indexOf("prefix") === -1 ? item : "prefix-new"); }); $(e).attr("class", classes.join(" "));` - Tim
更有效的解决方案使用map:$e.attr('class', $.map($e.attr('class').split(' '), function (klass) { return klass.indexOf(prefix) != 0 ? klass : undefined; }).join(' ')); - M Miller
2
这种方法效果最好。我使用了@JakubP的插件。如果可以提一个建议:现在返回类时,它会导致很多空格。例如,如果您运行removeClassPrefix("black");,则class="blackRow blackText orangeFace blackHead"将返回class=" orangeFace "。我通过像这样修剪结果来解决这个问题:el.className = $.trim(classes.join(" ")); - Bird87 ZA

61

使用jQuery时,实际的DOM元素位于索引0,这应该可以工作。

$('#a')[0].className = $('#a')[0].className.replace(/\bbg.*?\b/g, '');

36
注意这个问题。单词边界在破折号('-')和点号等字符上分割,因此类名如 "bg.a"、"bg-a" 等将不会被删除,而是被替换为 ".a"、"-a" 等。如果您的类名包含标点符号,您可能需要进行更复杂的正则表达式替换。这里是一个关于单词边界定义的 SO 讨论主题(https://dev59.com/33M_5IYBdhLWcg3wjj-r)。 - Jakub P.
6
在我看来,Kabir Sarin的回答使用split(' ')和indexOf更好,因为这不会导致那些带有特殊字符的“僵尸”类出现。 - Jakub P.
2
这种方法仍然可以使用更好的正则表达式,例如在此处找到的正则表达式:https://dev59.com/63E85IYBdhLWcg3wtV71#2644364 - ssmith

32

我写了一个简单的jQuery插件- alterClass,可以通配符方式删除类。也可以选择性地添加类。

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

谢谢Pete!刚刚使用了你的插件,非常好用...节省了我一些时间! - jordan.baucke

13

您不需要任何 jQuery 特定的代码来处理此问题。只需使用正则表达式进行替换:

$("#a").className = $("#a").className.replace(/\bbg.*?\b/g, '');

你可以修改这个来支持任何前缀,但更快的方法在于使用上面提到的正则表达式,因为它只需要编译一次:
function removeClassByPrefix(el, prefix) {
    var regx = new RegExp('\\b' + prefix + '.*?\\b', 'g');
    el.className = el.className.replace(regx, '');
    return el;
}

如果前缀以破折号结尾,则需要更改正则表达式。 new RegExp('\\b' + prefix + '[\\S]*\\b', 'g') - yaroslawww

9

使用$.fn.removeClass第二个签名

// Considering:
var $el = $('<div class="  foo-1 a b foo-2 c foo"/>');

function makeRemoveClassHandler(regex) {
  return function (index, classes) {
    return classes.split(/\s+/).filter(function (el) {return regex.test(el);}).join(' ');
  }
}

$el.removeClass(makeRemoveClassHandler(/^foo-/));
//> [<div class=​"a b c foo">​</div>​]

自从jQuery v1.4以来,这是最佳方法。 - Dinei

5

对于现代浏览器:

let element = $('#a')[0];
let cls = 'bg';

element.classList.remove.apply(element.classList, Array.from(element.classList).filter(v=>v.startsWith(cls)));

使用 string.startsWith()(或 string.endsWith())对我来说非常完美! - cuka

3

我会使用简单的jQuery结构和数组处理函数来实现一种方法,它会声明一个函数,该函数需要控件的id和类的前缀,并删除所有类。代码如下:

function removeclasses(controlIndex,classPrefix){
    var classes = $("#"+controlIndex).attr("class").split(" ");
    $.each(classes,function(index) {
        if(classes[index].indexOf(classPrefix)==0) {
            $("#"+controlIndex).removeClass(classes[index]);
        }
    });
}

现在这个函数可以从任何地方调用,比如从按钮的onclick事件或代码中:
removeclasses("a","bg");

2

一行代码移除所有符合正则表达式 someRegExp 的类名。

$('#my_element_id').removeClass( function() { return (this.className.match(/someRegExp/g) || []).join(' ').replace(prog.status.toLowerCase(),'');});

2

我正在寻找解决方案,来解决与这个问题完全相同的问题。要删除所有以前缀“fontid_”开头的类。阅读了这篇文章后,我编写了一个小插件,现在正在使用。

(function ($) {
        $.fn.removePrefixedClasses = function (prefix) {
            var classNames = $(this).attr('class').split(' '),
                className,
                newClassNames = [],
                i;
            //loop class names
            for(i = 0; i < classNames.length; i++) {
                className = classNames[i];
                // if prefix not found at the beggining of class name
                if(className.indexOf(prefix) !== 0) {
                    newClassNames.push(className);
                    continue;
                }
            }
            // write new list excluding filtered classNames
            $(this).attr('class', newClassNames.join(' '));
        };
    }(fQuery));

使用方法:

$('#elementId').removePrefixedClasses('prefix-of-classes_');

这只是我的解决方案,代码行数增加了10倍,而且“字符串以...开头”的检查效率更低 :-/ - Kabir Sarin

2

这是更好的选择!有效。 - Afshin Mehrabani
12
该问题并不是询问如何删除所有类(class),而是询问如何删除以特定字符串开头的所有类(class)。这两件事情非常、非常不同。 - Chris Harrison

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