首页 > 解决方案 > Chrome 陷入低效的正则表达式、HTML 输入模式或 AngularJS 自定义验证器

问题描述

我将尝试逐步解释问题。

我在 AngularJS 中编写了一些自定义验证器作为指令和服务。这是代码:

//validators.service.ts

@Injectable()
export class ValidatorsService {

  constructor() { }

  email():ValidatorFn {
    return (control: FormControl) => {
      if (!isNullOrUndefined(control.value) && control.value !== '') {
        const isValid = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(control.value);
        if (isValid) return null;
        return { emailValidator: { valid: false } }
      }

      return null
    };
  }
}


//email.directive.ts
@Directive({
  selector: '[appEmailValidator]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useClass: EmailValidatorDirective,
      multi: true
    }
  ]
})
export class EmailValidatorDirective implements Validator {

  validator: ValidatorFn;
  
  constructor(private validatorsService: ValidatorsService) {
    this.validator = this.validatorsService.email()
  }

  validate(c: FormControl) {
    return this.validator(c);
  }

}

我这样使用:

<input 
  pInputText 
  id="email" 
  name="email" 
  appEmailValidator 
  [(ngModel)]="mymodel" 
  required>

或像这样:

//*.component.html

<input 
  type="email" 
  pInputText 
  id="email"
  formControlName="email" name="email">


//*.component.ts

ngOnInit() {
        this.actorForm = new FormGroup({
            email: new FormControl('', [this.validatorsService.email(), Validators.required]),
        });
    }

它在正则表达式方面完美运行:“my@email.com”被接受,而“my@email.long”没有。

当我输入更多字符(尤其是超过 26 个字符)时,问题就出现了:Chrome 卡住了,我无法输入任何新字符,我的 CPU 使用率达到 100% 并且它基本上崩溃了,甚至无法重新加载页面。例如,Safari 不会发生这种情况。

所以:

• 我尝试将我的服务转换为简单的功能,但没有任何改变。

• 我删除了 PrimeNg 指令,认为它可能会导致问题,但没有。

• 我删除了该指令并尝试使用 HTML 模式,但什么也没有。

• 我删除了整个 ngModel 指令并且它起作用了,所以它与 Angular 有某种关系。此外,它通过绑定事件(change)=inputChanged($event)和更新模型来工作:

inputChanged(e){
  this.model = event.target.value
}

• 然后,我尝试仅删除事件绑定:[ngModel]="model"使用 HTML 输入模式,不。

• 我将我的 Angular 版本更新到了最新版本(我使用的是 4.3.1 版本),什么也没有。

• 我将我的正则表达式更改为/.+/它并且它工作了,即使它没用,我也知道问题与我的正则表达式和 ngModel 有关。

因此,我阅读了这些问题:

HTML 输入模式不起作用

Chrome 模式输入验证的正则表达式

即使我没有任何错误,并且正如我所说,它最初可以正常工作,我将每个转换 \..,再次,没有任何改变。

我的正则表达式有什么问题?你有没有遇到过这个问题?你有解决方法吗?

我想使用 Angular 功能,但似乎不太可能。

更新

看来我不是唯一一个不得不处理这个错误的人:

https://github.com/angular/angular/issues/12753

Angularjs输入字段卡在谷歌浏览器中输入

但它仍然没有解决。

• 我尝试按照 github 中的某个人的建议对输入进行去抖动,但它不起作用。

• 我从字面上复制并粘贴了 Angular 用作电子邮件验证器的相同 Regex:

/^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

它奏效了。

我的正则表达式效率低吗?如果是这样的话,它也不会在其他浏览器中工作,不是吗?

更新

• 我绑定了inputandkeyup事件并在JS 中移动了我的逻辑(没有HTML 模式,但我认为没关系)。它不起作用,即使有 1 秒的去抖动。然而,正如我所说,该change事件有效。

• 我试图myRegex.test(myLongString)了解这是否必须处理事件。令人惊讶的是,铬无论如何都会卡住。我不知道为什么这个change活动有效。也许,我没有正确测试它。

我解决这个问题的唯一方法是修改我的正则表达式:

/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/

( https://emailregex.com/ )

这比 Angular 的要好得多。

仅供参考,我发布了一些我所做的测试。

验证 => 有效

无效 => 无效

新的工作正则表达式 (emailregex.com)

新的工作正则表达式 (emailregex.com)

我的旧(不工作)正则表达式 新的工作正则表达式 (emailregex.com)

角正则表达式

角正则表达式

标签: javascripthtmlangularregexgoogle-chrome

解决方案


推荐阅读