国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

@angular/forms 源碼解析之 Validators

JowayYoung / 2020人閱讀

摘要:校驗器運行完成后,會設置屬性,從而計算的屬性,假設校驗錯誤,則屬性值為。這樣就理解了校驗器的整個運行過程,也包括為何校驗錯誤時會自動添加描述控件狀態的。

我們知道,@angular/forms 包主要用來解決表單問題的,而表單問題非常重要的一個功能就是表單校驗功能。數據校驗非常重要,不僅僅前端在發請求給后端前需要校驗數據,后端對前端發來的數據也需要校驗其有效性和邏輯性,尤其在存入數據庫前還得校驗數據的有效性。 @angular/forms 定義了一個 Validator 接口,并內置了 RequiredValidatorCheckboxRequiredValidatorEmailValidatorMinLengthValidatorMaxLengthValidatorPatternValidator 六個常用的校驗指令,每一個 validator 都實現了 Validator 接口。這些校驗指令的使用很簡單,比如使用 EmailValidatorRequiredValidator 指令來校驗輸入的數據得是 email 且不能為空:

這樣輸入的如果不是 email 格式,EmailValidator 指令就會校驗錯誤,會給 host(這里也就是 input 元素)添加 "ng-invalid" class,這樣開發者可以給這個 class 添加一些 css 效果,提高用戶體驗。那么,其內部運行過程是怎樣的呢?

實際上,上面 demo 中不僅僅綁定了 NgModel 指令,還綁定了 EmailValidatorRequiredValidator 兩個 validators 指令。指令在實例化時是按照聲明順序依次進行的,有依賴的指令則置后,FormsModule 先是聲明了 RequiredValidator 指令,然后是 EmailValidator 指令,最后才是 NgModel,所以實例化順序是 RequiredValidator -> EmailValidator -> NgModel,同時由于 NgModel 依賴于 NG_VALIDATORS,所以就算 NgModel 聲明在前也會被置后實例化。RequiredValidatorEmailValidator 在實例化過程中都會提供 REQUIRED_VALIDATOREMAIL_VALIDATOR 兩個服務,并且 StaticProvider 的 multi 屬性設置為 true,這樣可以容許有多個依賴服務(這里是 RequiredValidator 和 EmailValidator 對象)公用一個令牌(這里是 NG_VALIDATORS),multi 屬性作用可以查看源碼中說明。當 NgModel 實例化時,其構造依賴于 @Self() NG_VALIDATORS@Self() 表示從 NgModel 指令掛載的宿主元素中去查找這個令牌擁有的服務,NgModel 沒有提供 NG_VALIDATORS,但是掛載在 input 宿主元素上的 REQUIRED_VALIDATOREMAIL_VALIDATOR 卻提供了這個服務,所以 NgModel 的依賴 validators 就是這兩個指令組成的對象數組。

NgModel 在實例化時,由于沒有父控件容器,所以會調用 _setUpStandalone(),從而調用 setUpControl() 方法設置 FormControl 對象的 同步 validator 依賴(如果有異步 validator 依賴,也同理),這個依賴是調用 Validators.compose() 返回的一個 ValidatorFn 函數。而 Validators.compose() 參數調用的是 NgModel.validator,也就是調用 composeValidators 獲得 ValidatorFn,內部會調用 normalizeValidator() 函數轉換為為 (AbstractControl) => Validator.validate()。所以,和 input 控件綁定的 FormControl 對象就有了同步 validator 數據校驗器。那在 input 輸入框內輸入數據時,校驗器是在何時被運行的呢?

NgModel 實例化時,還安裝了一個 視圖數據更新回調,這樣當 input 視圖內的數據更新時,就會運行這個回調,該回調會更新 FormControl 的 value 值,即 FormControl.setValue() 函數,內部會調用 updateValueAndValidity,從而開始 運行數據校驗器,上文說到 FormControl 的 validator 依賴實際上是 Validators.compose() 返回的函數,所以此時會運行 這個回調函數,而這個 presentValidators 是 (AbstractControl) => RequiredValidator.validate() 和 (AbstractControl) => EmailValidator.validate() 組成的數組,然后依次 運行 這兩個 Validator 的 validate() 函數。如果校驗錯誤,就返回 ValidationErrors,比如 email 校驗器返回的是 {"email": true}。這里還需注意的是,Validator 指令里的 validate() 函數實際上調用的還是 Validator 類 的對應的靜態函數,這樣驗證器指令可以直接在模板里使用,而 Validator 類的靜態函數可以在 響應式表單 中使用。校驗器運行完成后,會設置 FormControl.errors 屬性,從而計算 FormControl 的 status 屬性,假設校驗錯誤,則 status 屬性值為 INVALID。那如果校驗錯誤,input 的 class 為何會添加 "ng-invalid" 呢?因為實際上還有一個 NgControlStatus 指令 也在綁定這個 input 元素,該指令的依賴會從當前掛載的宿主元素查找 NgControl,本 demo 中就是 NgModel 指令,NgControlStatus 指令 的 host 屬性中的 "[class.ng-invalid]": "ngClassInvalid",會運行 ngClassInvalid() 函數判斷是否會有 "ng-invalid" class,而校驗錯誤時,該函數運行結果是 true,因為它讀取的是 FormControl.invalid 屬性,則 "ng-invalid" class 就會被添加到 input 元素上。同理,其他 class 如 pending、dirty 等也同樣道理。這樣就理解了校驗器的整個運行過程,也包括為何校驗錯誤時會自動添加描述控件狀態的 "ng-invalid" class

我們已經理解了 Validators 的內部運行流程,這樣寫一個自定義的 Validator 就很簡單了(當然,寫一個自定義的 Validator 不需要去了解 Validator 內部運行原理)。比如,寫一個自定義校驗器 ForbiddenValidator,input 輸入內容不能還有某些字符串,那可以模仿 @angular/forms 中的內置校驗器 MinLengthValidator 寫法:

import {Validators as FormValidators} from "@angular/forms";

export class Validators extends FormValidators {
  static forbidden(forbidden: string): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      return (new RegExp(forbidden)).test(control.value) ? {forbidden: true} : null;
    }
  }
}

export const FORBIDDEN_VALIDATOR: StaticProvider = {
  provide: NG_VALIDATORS,
  useExisting: forwardRef(() => ForbiddenValidator),
  multi: true
};

@Directive({
  selector:
    ":not([type=checkbox])[forbidden][formControlName],:not([type=checkbox])[forbidden][formControl],:not([type=checkbox])[forbidden][ngModel]",
  providers: [FORBIDDEN_VALIDATOR],
})
export class ForbiddenValidator implements Validator{
  private _onChange: () => void;
  private _validator: ValidatorFn;
  
  @Input() forbidden: string;
  
  ngOnChanges(changes: SimpleChanges) {
    if ("forbidden" in changes) {
      this._createValidator();
      if (this._onChange) this._onChange();
    }
  }
  
  registerOnValidatorChange(fn: () => void): void {
    this._onChange = fn;
  }
  
  validate(c: AbstractControl): ValidationErrors | null {
    return this.forbidden ? this._validator(c) : null;
  }
  
  private _createValidator(): void {
    this._validator = Validators.forbidden(this.forbidden);
  }
}

這樣就可以在組件模板中使用了:

@Component(
{
    template: `
        

Template-Driven Form

Reactive-Driven Form

Update Forbidden Text

` }) export class AppComponent { // custom validator forbiddenText = "test"; email = "test@test.com"; emailFormControl = new FormControl("test@test.com", [Validators.forbidden(this.forbiddenText)]); }

完整代碼可參見 stackblitz demo

所以,在理解了 Validator 內部運行原理后,不僅僅可以寫自定義的 Validator,該 Validator 可以用于模板驅動表單也可以用于響應式表單,還能明白為啥需要那么寫,這個很重要!

也可閱讀 @angular/forms 相關文章了解 NgModel 雙向綁定內部原理:@angular/forms 源碼解析之雙向綁定

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/96539.html

相關文章

  • @angular/forms 源碼解析雙向綁定

    摘要:由于的屬性提供了令牌,并且該令牌指向的對象就是,所以構造函數中注入的令牌包含的對象數組只有一個。這樣的構造函數里就會包含一個對象,然后把這個傳給對象,最后注冊回調,這樣以后值更新時就會運行。整個包的設計也是按照這種數據流形式,并不復雜。 我們知道,Angular 的 @angular/forms 包提供了 NgModel 指令,來實現雙向綁定,即把一個 JS 變量(假設為 name)與...

    yangrd 評論0 收藏0
  • angular6的響應式表單

    摘要:在模塊里面引入要使用響應式表單,就要從包中導入,并把它添加到你的的數組中。導入驗證器函數響應式表單包含了一組開箱即用的常用驗證器函數。這些驗證器屬性可以和響應式表單提供的內置驗證器組合使用。 1:在AppModule模塊里面引入 ReactiveFormsModule 要使用響應式表單,就要從@angular/forms包中導入ReactiveFormsModule,并把它添加到你的N...

    alogy 評論0 收藏0
  • angular6的響應式表單

    摘要:在模塊里面引入要使用響應式表單,就要從包中導入,并把它添加到你的的數組中。導入驗證器函數響應式表單包含了一組開箱即用的常用驗證器函數。這些驗證器屬性可以和響應式表單提供的內置驗證器組合使用。 1:在AppModule模塊里面引入 ReactiveFormsModule 要使用響應式表單,就要從@angular/forms包中導入ReactiveFormsModule,并把它添加到你的N...

    hzc 評論0 收藏0
  • angular6的響應式表單

    摘要:在模塊里面引入要使用響應式表單,就要從包中導入,并把它添加到你的的數組中。導入驗證器函數響應式表單包含了一組開箱即用的常用驗證器函數。這些驗證器屬性可以和響應式表單提供的內置驗證器組合使用。 1:在AppModule模塊里面引入 ReactiveFormsModule 要使用響應式表單,就要從@angular/forms包中導入ReactiveFormsModule,并把它添加到你的N...

    MycLambert 評論0 收藏0

發表評論

0條評論

JowayYoung

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<