【问题标题】:jQuery removeClass wildcardjQuery removeClass 通配符
【发布时间】:2011-02-08 07:32:13
【问题描述】:

有没有什么简单的方法可以去掉所有匹配的类,比如,

color-*

所以如果我有一个元素:

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

删除后会是

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

谢谢!

【问题讨论】:

标签: jquery html


【解决方案1】:

对于一个 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 方法,该方法遍历所有现有的类名,并针对给定的正则表达式逐个测试它们,因此在后台它为相同的工作做了更多的步骤。但是在实际使用中,差异可以忽略不计。

Speed comparison benchmark

【讨论】:

  • 为什么有两个选项?哪个是首选?两者的优点/缺点是什么。 PS,我最喜欢你的回答,但它可以使用一些澄清。
  • @ToddHorst 谢谢,我已经更新了答案。事实上,区别只是更短的代码与更好的性能。
【解决方案2】:

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

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

你会在 css 中设置它的样式,例如:[data-color="red"]{ color: tomato; }

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

【讨论】:

  • 漂亮干净
【解决方案3】:

删除任何以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】:

    您也可以使用 Element.classList 使用 vanilla JavaScript 执行此操作。也不需要使用正则表达式:

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

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

    【讨论】:

    • 我喜欢这个方法,但是有没有办法让这个函数更全球化?例如;要使用要删除的类名来提供参数来运行吗?我的事情会更好:)
    • 当然,您可以在函数中添加第二个参数作为类名前缀,然后在循环比较中使用它而不是“color-”。
    【解决方案5】:
    $('div').attr('class', function(i, c){
        return c.replace(/(^|\s)color-\S+/g, '');
    });
    

    【讨论】:

    • 我喜欢这个,因为它减少了开销并且直截了当。当 attr 做得更好时,为什么要使用删除类?
    • 我认为您需要防止空类 (c is undefined)?至少当我在此页面上尝试below in my plugin 时,$('a').stripClass('post', 1) 抛出“TypeError: Cannot call method 'replace' of undefined”
    • @Kobi 是的,我认为不可能过滤属性并返回没有它的结果——$('div[class]') 应该只返回带有class 的元素,无论它们是否有一个值与否。测试场景:jsfiddle.net/drzaus/m83mv
    • @Kobi - 我想我明白你的意思了;在像.removeProp('class').className=undefined 这样的极端情况下,过滤器[class] 仍然返回一些东西,它们只是undefined。所以从技术上讲,它仍然有一个类(而不是.removeAttr('class'),这就是为什么它破坏了你的功能而不是我的变体。jsfiddle.net/drzaus/m83mv/4
    • 添加快速测试对我有用:return c &amp;&amp; c.replace(/\bcolor-\S+/g, '');
    【解决方案6】:

    removeClass 函数采用自 jQuery 1.4 以来的函数参数。

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

    现场示例:http://jsfiddle.net/xa9xS/1409/

    【讨论】:

    • 我认为值得注意的是,这将捕获未从开头开始的匹配类的前导空格。 Javascript 不支持正向后视,因此您必须使用捕获组解决方法。然而,这还没有实际意义,因为 removeClass 函数会通过 classes = ( value || "" ).match( rnotwhite ) || []; 为您从类字符串中去除空格
    • 我最喜欢这个解决方案!如何检查要删除的两个或更多类?即sport-nav-color- ?
    • 你会如何匹配以*-color 结尾的类?
    • @lowtechsun 你可以像(color-|sport-|nav-) 这样添加你的正则表达式。它将匹配color-,或sport-,或nav-。所以,上面的答案会变成/(^|\s)(color-|sport-|nav-)\S+/g
    • 接受的答案是正确的,但习惯上,我会使用匹配任何单词边界的 \b 而不是更冗长的 (^|\s)。因此,例如,要删除由单词 magic 后跟一个非负整数组成的所有类,并且只删除那些,我会匹配 /\bmagic\d+\b/。
    【解决方案7】:

    我遇到了同样的问题,并提出了以下使用下划线的 _.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;
    });
    

    【讨论】:

    • 你能解释一下下划线在_.filter中的作用
    【解决方案8】:

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

     $.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 扩展方法。谢谢!
    【解决方案9】:

    这将有效地从节点的class 属性中删除所有以prefix 开头的类名。其他答案不支持 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 对象不是更有效吗?
    • @EmileBergeron - 是的!我会做出改变
    【解决方案10】:

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

    在我的情况下,我需要在单击事件上向 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:是的。我可能会这样做,因为它没有直接回答原始问题。我应该留下这个答案还是删除它?
    • 那时,风险自负,它既没有被否决也没有被投赞成票。因此,您可以毫无风险地将其转移到您自己的问题上。此外,通过检查是否已经存在关于此的问题,尽量避免重复。
    【解决方案11】:

    类似于@tremby 的answer,这里是@Kobi 的answer 作为一个匹配前缀或后缀的插件。

    • ex) 剥离 btn-minibtn-danger 但不剥离 btn stripClass("btn-")
    • ex) 剥离 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

    【讨论】:

    • 为了记录,我不同意这更简单。
    • @tremby 抱歉,我的意思是 典型 用法更简单(即前缀和后缀),因为您不必每次都编写正则表达式
    • 我还是不同意。使用您的方法,您必须阅读文档并记住 endOrBegin 的确切值需要是什么。这不是不言自明的。写一个正则表达式有什么难的? /^match-at-start//match-at-end$/ 是每个 JS 开发人员都知道的。但各有千秋。
    • @tremby 除了正则表达式乞求被滥用之外,非正则表达式选项更匹配addClassremoveClasstoggleClass 的现有签名,这是每个 jQuery 开发人员都知道的.阅读文档有什么难的? ;)
    • 阅读文档并不难,但正如@tremby 所说,他的解决方案是不言自明的,而您的解决方案需要文档。根据定义,不言自明的解决方案更易于使用。
    【解决方案12】:

    基于ARS81answer(只匹配以开头的类名),这里有一个更灵活的版本。还有一个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;
    };
    

    【讨论】:

      【解决方案13】:

      如果你有多个元素的类名为“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-]* 放在您的正则表达式中,它不会删除名称中包含数字或某些“-”的类。

      【讨论】:

        【解决方案14】:

        我们可以通过.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)
        【解决方案15】:

        单词边界\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;
        };
        

        【讨论】:

          【解决方案16】:

          我已将其概括为一个 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-/)
          

          请注意,我正在使用 IEArray.filter 函数。您可以改用Underscore's filter function 或Google 来使用this WTFPL one 之类的polyfill。

          【讨论】:

            【解决方案17】:

            我编写了一个插件来执行此操作,称为 alterClass – 使用通配符匹配删除元素类。可选择添加类:https://gist.github.com/1517285

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

            【讨论】:

            • 确实非常好...帮助我重用了一些我只需要删除 Twitter Boostrap 类的代码,如下所示:$(".search div").children('div').alterClass('span* row-fluid');
            【解决方案18】:

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2010-11-26
              • 2011-02-01
              • 2013-02-18
              • 1970-01-01
              • 1970-01-01
              • 2020-09-18
              • 1970-01-01
              相关资源
              最近更新 更多