简体   繁体   English

全局字符串替换RegExp不会删除所有匹配项

[英]Global string replace RegExp not removing all matches

I'm creating some small add/remove/toggle/has class functions, they all work really well, until I've got multiple instances of the same class name value on a class. 我正在创建一些小的add / remove / toggle / has类函数,它们都工作得很好,直到在一个类上有多个具有相同类名值的实例为止。

Here's where I'm at so far, you'll see I have the 'g' flag in my removeClass Regexp: 这是我到目前为止的位置,您将在removeClass Regexp中看到“ g”标志:

Element.prototype.hasClass = function (className) {
    return new RegExp('(\\s|^)' + className + '(\\s|$)').test(this.className);
};

Element.prototype.addClass = function (className) {
    if (!this.hasClass(className)) {
        this.className += ' ' + className;
    }
};

Element.prototype.removeClass = function (className) {
    if (this.hasClass(className)) {
        this.className = this.className.replace(new RegExp('(\\s|^)' + className + '(\\s|$)', 'g'), '$2');
    }
};

Element.prototype.toggleClass = function (className) {
    if (this.hasClass(className)) {
        this.removeClass(className);
    } else {
        this.addClass(className);
    }
};

The starting HTML: 起始HTML:

<p class=" james james dean james james james">Hello</p>

When rendered: 呈现时:

<p class=" james dean james">Hello</p>

Here's my working jsFiddle, if you inspect element you can see not all james instances have been removed. 这是我正在工作的jsFiddle,如果您检查元素,您会发现并非所有james实例都已被删除。 Can anyone shed light as to what I'm doing wrong? 任何人都可以了解我在做什么错吗? Thanks in advance :) http://jsfiddle.net/8urPs/ 在此先感谢:) http://jsfiddle.net/8urPs/

You're expecting the class string to always be surrounded by white-space. 您期望类字符串始终被空格包围。 Once a white-space is matched it can't be matched again. 空格匹配后,便无法再次匹配。 So if there are two james classes standing next to each other and separated by one white-space, the first james will match and steal the white-space. 因此,如果有两个james类彼此相邻并被一个空格隔开,则第一个james将匹配并窃取该空格。 Then the second james won't match. 然后第二个james将不匹配。
To resolve the problem add * after each bracket. 要解决此问题,请在每个方括号后添加* It stands for zero or more of the preceding element . 它代表零个或多个前面的元素

new RegExp('(\\s|^) ' + className + '(\\s|$) ', 'g') new RegExp('(\\ s | ^) '+ className +'(\\ s | $) ','g')

Here's your update fiddle: http://jsfiddle.net/8urPs/1/ 这是您的更新小提琴: http : //jsfiddle.net/8urPs/1/

Update 更新

According to your comment about multiple white-spaces - the problem was the replacement value. 根据您对多个空格的评论-问题是替换值。 In the first approach I left it unchanged - $2 . 在第一种方法中,我将其保留不变- $2 Actually, we don't need any content in the replacement, so we can simply change it to an empty string 实际上,替换中不需要任何内容​​,因此我们只需将其更改为空字符串即可

this.className = this.className.replace(new RegExp('(\\s|^)*' + className + '(\\s|$)*', 'g'), '');

Here's the corrected fiddle: http://jsfiddle.net/8urPs/2/ 这是更正后的小提琴: http : //jsfiddle.net/8urPs/2/

You have a problem with overlapping expressions. 表达式重叠存在问题。 You are replacing james ; 您正在更换james however, in james james , the middle space is shared, and regexps won't match overlapping spans. 但是,在james james ,中间空间是共享的,并且正则表达式将不匹配重叠的跨度。

Rewrite to either use word boundaries ( \\b ) instead of spaces and beg/end, or with lookahead so as not to consume that space. 改写为使用单词边界( \\b )代替空格和beg / end,或者使用超前方式以免占用该空格。

It is because the spaces between the class names can only be part of a single match. 这是因为类名之间的空格只能是单个匹配项的一部分。 To fix this, you can replace the final capturing group with a positive lookaheaed, like so: 要解决此问题,您可以使用积极的外观替换最终的捕获组,如下所示:

Element.prototype.removeClass = function (className) {
    if (this.hasClass(className)) {
        this.className = this.className.replace(new RegExp('(\\s|^)' + className + '(?=\\s|$)', 'g'), '');
    }
};

White space after className is always matched, and then cannot be matched again. className之后的空格始终匹配,然后无法再次匹配。 Using positive lookahead assertion can help you with that: 使用正向超前断言可以帮助您:

this.className = this.className.replace(new RegExp('(\\s|^)' + className + '(?=\\s|$)', 'g'), '');

When you start capture group with ?= then it is trated as assertion and not matched. 当您使用?=开始捕获组时,它将被断言为断言并且不匹配。

Working sample: http://jsfiddle.net/ah3Ge/ 工作示例: http : //jsfiddle.net/ah3Ge/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM