javascript - 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 有关。
因此,我阅读了这些问题:
即使我没有任何错误,并且正如我所说,它最初可以正常工作,我将每个转换 \.
为.
,再次,没有任何改变。
我的正则表达式有什么问题?你有没有遇到过这个问题?你有解决方法吗?
我想使用 Angular 功能,但似乎不太可能。
更新
看来我不是唯一一个不得不处理这个错误的人:
https://github.com/angular/angular/issues/12753
但它仍然没有解决。
• 我尝试按照 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])?)*$/
它奏效了。
我的正则表达式效率低吗?如果是这样的话,它也不会在其他浏览器中工作,不是吗?
更新
• 我绑定了input
andkeyup
事件并在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,}))$/
这比 Angular 的要好得多。
仅供参考,我发布了一些我所做的测试。
验证 => 有效
无效 => 无效
新的工作正则表达式 (emailregex.com)
角正则表达式
解决方案
推荐阅读
- angular - Angular Material Mat-List-Option 复选框列表获取数据
- angular - CanActivate 守卫在初始加载时重定向到/,路由器出口不呈现
- android - 在 Okta 和 Xamarin.Forms 中使用重定向
- css - 循环进度显示100%以上
- html - 导航键在 ag 网格中的 cellrenderer 输入框中不起作用
- powershell - Windows 无法挂载非英语挂载点
- emacs - 无法响应 emacs 内的脚本提问
- javascript - 更新标记而不刷新页面
- c# - 如果列值匹配,我正在尝试删除数据表行
- android - 为什么我们不能从另一个对话框打开一个对话框?技术挑战是什么?