面试题答案
一键面试1. 设计可复用的表单验证指令
- 创建自定义验证器函数
- 在Angular中,可以使用
ValidatorFn
类型来定义自定义验证器函数。 - 以下是验证密码强度的自定义验证器函数示例:
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; export function passwordStrengthValidator(): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { const value = control.value; if (!value) { return null; } const hasUpperCase = /[A - Z]/.test(value); const hasLowerCase = /[a - z]/.test(value); const hasDigit = /\d/.test(value); const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value); const lengthIsValid = value.length >= 8 && value.length <= 16; if (hasUpperCase && hasLowerCase && hasDigit && hasSpecialChar && lengthIsValid) { return null; } return { passwordStrength: true }; }; }
- 在Angular中,可以使用
- 创建验证指令
- 使用
Directive
装饰器创建一个指令,将自定义验证器函数应用到表单控件上。
import { Directive } from '@angular/core'; import { NG_VALIDATORS, Validator, AbstractControl } from '@angular/forms'; import { passwordStrengthValidator } from './password - strength.validator'; @Directive({ selector: '[appPasswordStrength]', providers: [ { provide: NG_VALIDATORS, useExisting: PasswordStrengthDirective, multi: true } ] }) export class PasswordStrengthDirective implements Validator { validate(control: AbstractControl): { [key: string]: any } | null { return passwordStrengthValidator()(control); } }
- 使用
- 在模板中使用指令
- 在表单输入框中使用自定义的验证指令。
<input type="password" formControlName="password" appPasswordStrength>
2. 性能优化
- 防抖(Debounce)
- 对于密码验证这种用户输入时实时触发的验证,使用防抖机制可以减少不必要的计算。
- 可以使用
rxjs
的debounceTime
操作符。例如,在表单组件的ngOnInit
方法中:
import { Component } from '@angular/core'; import { FormControl } from '@angular/forms'; import { debounceTime } from 'rxjs/operators'; @Component({ selector: 'app - password - form', templateUrl: './password - form.component.html' }) export class PasswordFormComponent { passwordControl = new FormControl(''); ngOnInit() { this.passwordControl.valueChanges.pipe( debounceTime(300) ).subscribe(() => { // 这里会在用户停止输入300毫秒后触发验证,减少了频繁验证的计算 this.passwordControl.updateValueAndValidity(); }); } }
- 避免不必要的DOM操作
- Angular的变更检测机制默认会在每次数据变化时检查整个组件树。为了减少不必要的DOM操作,可以:
- 使用
OnPush
策略:在组件定义时,将changeDetection
设置为ChangeDetectionStrategy.OnPush
。这样只有当组件的输入属性或事件触发时才会进行变更检测,减少了不必要的检查。
import { Component, ChangeDetectionStrategy } from '@angular/core'; @Component({ selector: 'app - password - form', templateUrl: './password - form.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) export class PasswordFormComponent { // 组件逻辑 }
- 使用
- 局部更新:尽量避免直接操作DOM。如果需要根据验证结果更新DOM元素的样式,使用Angular的
ngClass
等指令。例如:
这样Angular会在验证结果变化时,通过<input type="password" formControlName="password" appPasswordStrength> <div [ngClass]="{ 'invalid - password': passwordControl.hasError('passwordStrength') }"> 密码强度不符合要求 </div>
ngClass
指令局部更新DOM的类,而不是重新渲染整个组件。 - Angular的变更检测机制默认会在每次数据变化时检查整个组件树。为了减少不必要的DOM操作,可以: