国产gaysexchina男同gay,japanrcep老熟妇乱子伦视频,吃奶呻吟打开双腿做受动态图,成人色网站,国产av一区二区三区最新精品

Angular9 生命周期鉤子

2020-07-01 11:23 更新

當(dāng) Angular 實(shí)例化組件類并渲染組件視圖及其子視圖時(shí),組件實(shí)例的生命周期就開始了。生命周期一直伴隨著變更檢測(cè),Angular 會(huì)檢查數(shù)據(jù)綁定屬性何時(shí)發(fā)生變化,并按需更新視圖和組件實(shí)例。當(dāng) Angular 銷毀組件實(shí)例并從 DOM 中移除它渲染的模板時(shí),生命周期就結(jié)束了。當(dāng) Angular 在執(zhí)行過程中創(chuàng)建、更新和銷毀實(shí)例時(shí),指令就有了類似的生命周期。

你的應(yīng)用可以使用生命周期鉤子方法來觸發(fā)組件或指令生命周期中的關(guān)鍵事件,以初始化新實(shí)例,需要時(shí)啟動(dòng)變更檢測(cè),在變更檢測(cè)過程中響應(yīng)更新,并在刪除實(shí)例之前進(jìn)行清理。

先決條件

在使用生命周期鉤子之前,你應(yīng)該對(duì)這些內(nèi)容有一個(gè)基本的了解:

  • TypeScript 編程 。

  • Angular 應(yīng)用設(shè)計(jì)基礎(chǔ),就像 Angular 的基本概念中所講的那樣。

響應(yīng)生命周期事件

你可以通過實(shí)現(xiàn)一個(gè)或多個(gè) Angular core 庫中定義的生命周期鉤子接口來響應(yīng)組件或指令生命周期中的事件。這些鉤子讓你有機(jī)會(huì)在適當(dāng)?shù)臅r(shí)候?qū)M件或指令實(shí)例進(jìn)行操作,比如 Angular 創(chuàng)建、更新或銷毀這個(gè)實(shí)例時(shí)。

每個(gè)接口都有唯一的一個(gè)鉤子方法,它們的名字是由接口名再加上 ng 前綴構(gòu)成的。比如,OnInit 接口的鉤子方法叫做 ngOnInit()。如果你在組件或指令類中實(shí)現(xiàn)了這個(gè)方法,Angular 就會(huì)在首次檢查完組件或指令的輸入屬性后,緊接著調(diào)用它。

Path:"peek-a-boo.component.ts (excerpt)" 。

@Directive()
export class PeekABooDirective implements OnInit {
  constructor(private logger: LoggerService) { }


  // implement OnInit's `ngOnInit` method
  ngOnInit() { this.logIt(`OnInit`); }


  logIt(msg: string) {
    this.logger.log(`#${nextId++} ${msg}`);
  }
}

注:
- 你不必實(shí)現(xiàn)所有生命周期鉤子,只要實(shí)現(xiàn)你需要的那些就可以了。

生命周期的順序

當(dāng)你的應(yīng)用通過調(diào)用構(gòu)造函數(shù)來實(shí)例化一個(gè)組件或指令時(shí),Angular 就會(huì)調(diào)用那個(gè)在該實(shí)例生命周期的適當(dāng)位置實(shí)現(xiàn)了的那些鉤子方法。

Angular 會(huì)按以下順序執(zhí)行鉤子方法。你可以用它來執(zhí)行以下類型的操作。

鉤子方法 用途 調(diào)用時(shí)機(jī)
ngOnChanges() 當(dāng) Angular 設(shè)置或重新設(shè)置數(shù)據(jù)綁定的輸入屬性時(shí)響應(yīng)。 該方法接受當(dāng)前和上一屬性值的 SimpleChanges 對(duì)象。注意,這發(fā)生的非常頻繁,所以你在這里執(zhí)行的任何操作都會(huì)顯著影響性能。 在 ngOnInit() 之前以及所綁定的一個(gè)或多個(gè)輸入屬性的值發(fā)生變化時(shí)都會(huì)調(diào)用。
ngOnInit() 在 Angular 第一次顯示數(shù)據(jù)綁定和設(shè)置指令/組件的輸入屬性之后,初始化指令/組件。 在第一輪 ngOnChanges() 完成之后調(diào)用,只調(diào)用一次。
ngDoCheck() 檢測(cè),并在發(fā)生 Angular 無法或不愿意自己檢測(cè)的變化時(shí)作出反應(yīng)。 緊跟在每次執(zhí)行變更檢測(cè)時(shí)的 ngOnChanges() 和 首次執(zhí)行變更檢測(cè)時(shí)的 ngOnInit() 后調(diào)用。
ngAfterContentInit() 當(dāng) Angular 把外部?jī)?nèi)容投影進(jìn)組件視圖或指令所在的視圖之后調(diào)用。 第一次 ngDoCheck() 之后調(diào)用,只調(diào)用一次。
ngAfterContentChecked() 每當(dāng) Angular 檢查完被投影到組件或指令中的內(nèi)容之后調(diào)用。 ngAfterContentInit() 和每次 ngDoCheck() 之后調(diào)用
ngAfterViewInit() 當(dāng) Angular 初始化完組件視圖及其子視圖或包含該指令的視圖之后調(diào)用。 第一次 ngAfterContentChecked() 之后調(diào)用,只調(diào)用一次。
ngAfterViewChecked() 每當(dāng) Angular 做完組件視圖和子視圖或包含該指令的視圖的變更檢測(cè)之后調(diào)用。 ngAfterViewInit() 和每次 ngAfterContentChecked() 之后調(diào)用。
ngOnDestroy() 每當(dāng) Angular 每次銷毀指令/組件之前調(diào)用并清掃。 在這兒反訂閱可觀察對(duì)象和分離事件處理器,以防內(nèi)存泄漏。 在 Angular 銷毀指令或組件之前立即調(diào)用。

生命周期范例

通過在受控于根組件 AppComponent 的一些組件上進(jìn)行的一系列練習(xí),演示了生命周期鉤子的運(yùn)作方式。 每一個(gè)例子中,父組件都扮演了子組件測(cè)試臺(tái)的角色,以展示出一個(gè)或多個(gè)生命周期鉤子方法。

下表列出了這些練習(xí)及其簡(jiǎn)介。 范例代碼也用來闡明后續(xù)各節(jié)的一些特定任務(wù)。

組件 說明
Peek-a-boo 展示每個(gè)生命周期鉤子,每個(gè)鉤子方法都會(huì)在屏幕上顯示一條日志。
Spy 展示了你如何在自定義指令中使用生命周期鉤子。 SpyDirective 實(shí)現(xiàn)了 ngOnInit() 和 ngOnDestroy() 鉤子,并且使用它們來觀察和匯報(bào)一個(gè)元素何時(shí)進(jìn)入或離開當(dāng)前視圖。
OnChanges 演示了每當(dāng)組件的輸入屬性之一發(fā)生變化時(shí),Angular 如何調(diào)用 ngOnChanges() 鉤子。并且演示了如何解釋傳給鉤子方法的 changes 對(duì)象。
DoCheck 實(shí)現(xiàn)了一個(gè) ngDoCheck() 方法,通過它可以自定義變更檢測(cè)邏輯。 監(jiān)視該鉤子把哪些變更記錄到了日志中,觀察 Angular 以什么頻度調(diào)用這個(gè)鉤子。
AfterView 顯示 Angular 中的視圖所指的是什么。 演示了 ngAfterViewInit() 和 ngAfterViewChecked() 鉤子。
AfterContent 展示如何把外部?jī)?nèi)容投影進(jìn)組件中,以及如何區(qū)分“投影進(jìn)來的內(nèi)容”和“組件的子視圖”。 演示了 ngAfterContentInit() 和 ngAfterContentChecked() 鉤子。
計(jì)數(shù)器 演示了一個(gè)組件和一個(gè)指令的組合,它們各自有自己的鉤子。

初始化組件或指令

使用 ngOnInit() 方法執(zhí)行以下初始化任務(wù)。

  • 在構(gòu)造函數(shù)外部執(zhí)行復(fù)雜的初始化。組件的構(gòu)造應(yīng)該既便宜又安全。比如,你不應(yīng)該在組件構(gòu)造函數(shù)中獲取數(shù)據(jù)。當(dāng)在測(cè)試中創(chuàng)建組件時(shí)或者決定顯示它之前,你不應(yīng)該擔(dān)心新組件會(huì)嘗試聯(lián)系遠(yuǎn)程服務(wù)器。

ngOnInit() 是組件獲取初始數(shù)據(jù)的好地方。比如,英雄指南 中的《在 ngOnInit() 中調(diào)用它》小節(jié)。

  • 在 Angular 設(shè)置好輸入屬性之后設(shè)置組件。構(gòu)造函數(shù)應(yīng)該只把初始局部變量設(shè)置為簡(jiǎn)單的值。

請(qǐng)記住,只有在構(gòu)造完成之后才會(huì)設(shè)置指令的數(shù)據(jù)綁定輸入屬性。如果要根據(jù)這些屬性對(duì)指令進(jìn)行初始化,請(qǐng)?jiān)谶\(yùn)行 ngOnInit() 時(shí)設(shè)置它們。

&ngOnChanges() 方法是你能訪問這些屬性的第一次機(jī)會(huì)。Angular 會(huì)在調(diào)用 ngOnInit() 之前調(diào)用 ngOnChanges(),而且之后還會(huì)調(diào)用多次。但它只調(diào)用一次 ngOnInit()。

在實(shí)例銷毀時(shí)進(jìn)行清理

把清理邏輯放進(jìn) ngOnDestroy() 中,這個(gè)邏輯就必然會(huì)在 Angular 銷毀該指令之前運(yùn)行。

這里是釋放資源的地方,這些資源不會(huì)自動(dòng)被垃圾回收。如果你不這樣做,就存在內(nèi)存泄漏的風(fēng)險(xiǎn)。

  • 取消訂閱可觀察對(duì)象和 DOM 事件。

  • 停止 interval 計(jì)時(shí)器。

  • 反注冊(cè)該指令在全局或應(yīng)用服務(wù)中注冊(cè)過的所有回調(diào)。

ngOnDestroy() 方法也可以用來通知應(yīng)用程序的其它部分,該組件即將消失。

一般性例子

下面的例子展示了各個(gè)生命周期事件的調(diào)用順序和相對(duì)頻率,以及如何在組件和指令中單獨(dú)使用或同時(shí)使用這些鉤子。

所有生命周期事件的順序和頻率

為了展示 Angular 如何以預(yù)期的順序調(diào)用鉤子,PeekABooComponent 演示了一個(gè)組件中的所有鉤子。

實(shí)際上,你很少會(huì)(幾乎永遠(yuǎn)不會(huì))像這個(gè)演示中一樣實(shí)現(xiàn)所有這些接口。

下列快照反映了用戶單擊 Create... 按鈕,然后單擊 Destroy... 按鈕后的日志狀態(tài)。

日志信息的日志和所規(guī)定的鉤子調(diào)用順序是一致的: OnChangesOnInit、DoCheck (3x)AfterContentInit、AfterContentChecked (3x)AfterViewInit、AfterViewChecked (3x)OnDestroy 。

注:
- 該日志確認(rèn)了在創(chuàng)建期間那些輸入屬性(這里是 name 屬性)沒有被賦值。 這些輸入屬性要等到 onInit() 中才可用,以便做進(jìn)一步的初始化。

如果用戶點(diǎn)擊 Update Hero 按鈕,就會(huì)看到另一個(gè) OnChanges 和至少兩組 DoCheck、AfterContentCheckedAfterViewChecked 鉤子。 注意,這三種鉤子被觸發(fā)了很多次,所以讓它們的邏輯盡可能保持精簡(jiǎn)是非常重要的!

使用指令來監(jiān)視 DOM

這個(gè) Spy 例子演示了如何在指令和組件中使用鉤子方法。SpyDirective 實(shí)現(xiàn)了兩個(gè)鉤子 ngOnInit()ngOnDestroy(),以便發(fā)現(xiàn)被監(jiān)視的元素什么時(shí)候位于當(dāng)前視圖中。

這個(gè)模板將 SpyDirective 應(yīng)用到由父組件 SpyComponent 管理的 ngFor 內(nèi)的 <div> 中。

該例子不執(zhí)行任何初始化或清理工作。它只是通過記錄指令本身的實(shí)例化時(shí)間和銷毀時(shí)間來跟蹤元素在視圖中的出現(xiàn)和消失。

像這樣的間諜指令可以深入了解你無法直接修改的 DOM 對(duì)象。你無法觸及原生 <div> 的實(shí)現(xiàn),也無法修改第三方組件,但是可以用指令來監(jiān)視這些元素。

這個(gè)指令定義了 ngOnInit()ngOnDestroy() 鉤子,它通過一個(gè)注入進(jìn)來的 LoggerService 把消息記錄到父組件中去。

Path:"src/app/spy.directive.ts" 。

// Spy on any element to which it is applied.
// Usage: <div mySpy>...</div>
@Directive({selector: '[mySpy]'})
export class SpyDirective implements OnInit, OnDestroy {


  constructor(private logger: LoggerService) { }


  ngOnInit()    { this.logIt(`onInit`); }


  ngOnDestroy() { this.logIt(`onDestroy`); }


  private logIt(msg: string) {
    this.logger.log(`Spy #${nextId++} ${msg}`);
  }
}

你可以把這個(gè)偵探指令寫到任何原生元素或組件元素上,以觀察它何時(shí)被初始化和銷毀。 下面是把它附加到用來重復(fù)顯示英雄數(shù)據(jù)的這個(gè) <div> 上。

Path:"src/app/spy.component.html" 。

<div *ngFor="let hero of heroes" mySpy class="heroes">
  {{hero}}
</div>

每個(gè)“偵探”的創(chuàng)建和銷毀都可以標(biāo)出英雄所在的那個(gè) <div> 的出現(xiàn)和消失。鉤子記錄中的結(jié)構(gòu)是這樣的:

添加一個(gè)英雄就會(huì)產(chǎn)生一個(gè)新的英雄 <div>。偵探的 ngOnInit() 記錄下了這個(gè)事件。

Reset 按鈕清除了這個(gè) heroes 列表。 Angular 從 DOM 中移除了所有英雄的 div,并且同時(shí)銷毀了附加在這些 div 上的偵探指令。 偵探的 ngOnDestroy() 方法匯報(bào)了它自己的臨終時(shí)刻。

同時(shí)使用組件和指令的鉤子

在這個(gè)例子中,CounterComponent 使用了 ngOnChanges() 方法,以便在每次父組件遞增其輸入屬性 counter 時(shí)記錄一次變更。

這個(gè)例子將前例中的 SpyDirective 用于 CounterComponent 的日志,以便監(jiān)視這些日志條目的創(chuàng)建和銷毀。

使用變更檢測(cè)鉤子

一旦檢測(cè)到該組件或指令的輸入屬性發(fā)生了變化,Angular 就會(huì)調(diào)用它的 ngOnChanges() 方法。 這個(gè) onChanges 范例通過監(jiān)控 OnChanges() 鉤子演示了這一點(diǎn)。

Path:"on-changes.component.ts (excerpt)" 。

ngOnChanges(changes: SimpleChanges) {
  for (let propName in changes) {
    let chng = changes[propName];
    let cur  = JSON.stringify(chng.currentValue);
    let prev = JSON.stringify(chng.previousValue);
    this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
  }
}

ngOnChanges() 方法獲取了一個(gè)對(duì)象,它把每個(gè)發(fā)生變化的屬性名都映射到了一個(gè) SimpleChange 對(duì)象, 該對(duì)象中有屬性的當(dāng)前值和前一個(gè)值。這個(gè)鉤子會(huì)在這些發(fā)生了變化的屬性上進(jìn)行迭代,并記錄它們。

這個(gè)例子中的 OnChangesComponent 組件有兩個(gè)輸入屬性:heropower

Path:"src/app/on-changes.component.ts" 。

@Input() hero: Hero;
@Input() power: string;

宿主 OnChangesParentComponent 綁定了它們,就像這樣:

Path:"src/app/on-changes-parent.component.html" 。

<on-changes [hero]="hero" [power]="power"></on-changes>

下面是此例子中的當(dāng)用戶做出更改時(shí)的操作演示:

日志條目把 power 屬性的變化顯示為字符串。但請(qǐng)注意,ngOnChanges() 方法不會(huì)捕獲對(duì) hero.name 更改。這是因?yàn)橹挥挟?dāng)輸入屬性的值發(fā)生變化時(shí),Angular 才會(huì)調(diào)用該鉤子。在這種情況下,hero 是輸入屬性,hero 屬性的值是對(duì) hero 對(duì)象的引用 。當(dāng)它自己的 name 屬性的值發(fā)生變化時(shí),對(duì)象引用并沒有改變。

響應(yīng)視圖的變更

當(dāng) Angular 在變更檢測(cè)期間遍歷視圖樹時(shí),需要確保子組件中的某個(gè)變更不會(huì)嘗試更改其父組件中的屬性。因?yàn)閱蜗驍?shù)據(jù)流的工作原理就是這樣的,這樣的更改將無法正常渲染。

如果你需要做一個(gè)與預(yù)期數(shù)據(jù)流反方向的修改,就必須觸發(fā)一個(gè)新的變更檢測(cè)周期,以允許渲染這種變更。這些例子說明了如何安全地做出這些改變。

AfterView 例子展示了 AfterViewInit()AfterViewChecked() 鉤子,Angular 會(huì)在每次創(chuàng)建了組件的子視圖后調(diào)用它們。

下面是一個(gè)子視圖,它用來把英雄的名字顯示在一個(gè) <input> 中:

Path:"src/app/ChildComponent" 。

@Component({
  selector: 'app-child-view',
  template: '<input [(ngModel)]="hero">'
})
export class ChildViewComponent {
  hero = 'Magneta';
}

AfterViewComponent 把這個(gè)子視圖顯示在它的模板中:

Path:"src/app/AfterViewComponent (template)" 。

template: `
  <div>-- child view begins --</div>
    <app-child-view></app-child-view>
  <div>-- child view ends --</div>`

下列鉤子基于子視圖中的每一次數(shù)據(jù)變更采取行動(dòng),它只能通過帶@ViewChild裝飾器的屬性來訪問子視圖。

Path:"src/app/AfterViewComponent (class excerpts)" 。

export class AfterViewComponent implements  AfterViewChecked, AfterViewInit {
  private prevHero = '';


  // Query for a VIEW child of type `ChildViewComponent`
  @ViewChild(ChildViewComponent) viewChild: ChildViewComponent;


  ngAfterViewInit() {
    // viewChild is set after the view has been initialized
    this.logIt('AfterViewInit');
    this.doSomething();
  }


  ngAfterViewChecked() {
    // viewChild is updated after the view has been checked
    if (this.prevHero === this.viewChild.hero) {
      this.logIt('AfterViewChecked (no change)');
    } else {
      this.prevHero = this.viewChild.hero;
      this.logIt('AfterViewChecked');
      this.doSomething();
    }
  }
  // ...
}

在更新視圖之前等待

在這個(gè)例子中,當(dāng)英雄名字超過 10 個(gè)字符時(shí),doSomething() 方法會(huì)更新屏幕,但在更新 comment 之前會(huì)等一個(gè)節(jié)拍(tick)。

Path:"src/app/AfterViewComponent (doSomething)" 。

// This surrogate for real business logic sets the `comment`
private doSomething() {
  let c = this.viewChild.hero.length > 10 ? `That's a long name` : '';
  if (c !== this.comment) {
    // Wait a tick because the component's view has already been checked
    this.logger.tick_then(() => this.comment = c);
  }
}

在組件的視圖合成完之后,就會(huì)觸發(fā) AfterViewInit()AfterViewChecked() 鉤子。如果你修改了這段代碼,讓這個(gè)鉤子立即修改該組件的數(shù)據(jù)綁定屬性 comment,你就會(huì)發(fā)現(xiàn) Angular 拋出一個(gè)錯(cuò)誤。

LoggerService.tick_then() 語句把日志的更新工作推遲了一個(gè)瀏覽器 JavaScript 周期,也就觸發(fā)了一個(gè)新的變更檢測(cè)周期。

編寫精簡(jiǎn)的鉤子方法來避免性能問題

當(dāng)你運(yùn)行 AfterView 示例時(shí),請(qǐng)注意當(dāng)沒有發(fā)生任何需要注意的變化時(shí),Angular 仍然會(huì)頻繁的調(diào)用 AfterViewChecked()。 要非常小心你放到這些方法中的邏輯或計(jì)算量。

響應(yīng)被投影內(nèi)容的變更

內(nèi)容投影是從組件外部導(dǎo)入 HTML 內(nèi)容,并把它插入在組件模板中指定位置上的一種途徑。 你可以在目標(biāo)中通過查找下列結(jié)構(gòu)來認(rèn)出內(nèi)容投影。

  • 元素標(biāo)簽中間的 HTML。

  • 組件模板中的 <ng-content> 標(biāo)簽。

這個(gè) AfterContent 例子探索了 AfterContentInit() 和 AfterContentChecked() 鉤子。Angular 會(huì)在把外部?jī)?nèi)容投影進(jìn)該組件時(shí)調(diào)用它們。

對(duì)比前面的 AfterView 例子考慮這個(gè)變化。 這次不再通過模板來把子視圖包含進(jìn)來,而是改為從 AfterContentComponent 的父組件中導(dǎo)入它。下面是父組件的模板:

Path:"src/app/AfterContentParentComponent (template excerpt)" 。

`<after-content>
   <app-child></app-child>
 </after-content>`

注意,<app-child> 標(biāo)簽被包含在 <after-content> 標(biāo)簽中。 永遠(yuǎn)不要在組件標(biāo)簽的內(nèi)部放任何內(nèi)容 —— 除非你想把這些內(nèi)容投影進(jìn)這個(gè)組件中。

現(xiàn)在來看該組件的模板:

Path:"src/app/AfterContentComponent (template)" 。

template: `
  <div>-- projected content begins --</div>
    <ng-content></ng-content>
  <div>-- projected content ends --</div>`

<ng-content> 標(biāo)簽是外來內(nèi)容的占位符。 它告訴 Angular 在哪里插入這些外來內(nèi)容。 在這里,被投影進(jìn)去的內(nèi)容就是來自父組件的 <app-child> 標(biāo)簽。

使用 AfterContent 鉤子

AfterContent 鉤子和 AfterView 相似。關(guān)鍵的不同點(diǎn)是子組件的類型不同。

AfterView 鉤子所關(guān)心的是 ViewChildren,這些子組件的元素標(biāo)簽會(huì)出現(xiàn)在該組件的模板里面。

AfterContent 鉤子所關(guān)心的是 ContentChildren,這些子組件被 Angular 投影進(jìn)該組件中。

下列 AfterContent 鉤子基于子級(jí)內(nèi)容中值的變化而采取相應(yīng)的行動(dòng),它只能通過帶有 @ContentChild 裝飾器的屬性來查詢到“子級(jí)內(nèi)容”。

Path:"src/app/AfterContentComponent (class excerpts)" 。

export class AfterContentComponent implements AfterContentChecked, AfterContentInit {
  private prevHero = '';
  comment = '';


  // Query for a CONTENT child of type `ChildComponent`
  @ContentChild(ChildComponent) contentChild: ChildComponent;


  ngAfterContentInit() {
    // contentChild is set after the content has been initialized
    this.logIt('AfterContentInit');
    this.doSomething();
  }


  ngAfterContentChecked() {
    // contentChild is updated after the content has been checked
    if (this.prevHero === this.contentChild.hero) {
      this.logIt('AfterContentChecked (no change)');
    } else {
      this.prevHero = this.contentChild.hero;
      this.logIt('AfterContentChecked');
      this.doSomething();
    }
  }
  // ...
}

&- 不需要等待內(nèi)容更新

&- 該組件的 doSomething() 方法會(huì)立即更新該組件的數(shù)據(jù)綁定屬性 comment。而無需延遲更新以確保正確渲染 。

&- Angular 在調(diào)用 AfterView 鉤子之前,就已調(diào)用完所有的 AfterContent 鉤子。 在完成該組件視圖的合成之前, Angular 就已經(jīng)完成了所投影內(nèi)容的合成工作。 AfterContent... 和 AfterView... 鉤子之間有一個(gè)小的時(shí)間窗,允許你修改宿主視圖。

自定義變更檢測(cè)邏輯

要監(jiān)控 ngOnChanges() 無法捕獲的變更,你可以實(shí)現(xiàn)自己的變更檢查邏輯,比如 DoCheck 的例子。這個(gè)例子展示了你如何使用 ngDoCheck() 鉤子來檢測(cè)和處理 Angular 自己沒有捕捉到的變化。

DoCheck 示例使用下面的 ngDoCheck() 鉤子擴(kuò)展了 OnChanges 示例:

Path:"src/app/DoCheckComponent (ngDoCheck)" 。

ngDoCheck() {


  if (this.hero.name !== this.oldHeroName) {
    this.changeDetected = true;
    this.changeLog.push(`DoCheck: Hero name changed to "${this.hero.name}" from "${this.oldHeroName}"`);
    this.oldHeroName = this.hero.name;
  }


  if (this.power !== this.oldPower) {
    this.changeDetected = true;
    this.changeLog.push(`DoCheck: Power changed to "${this.power}" from "${this.oldPower}"`);
    this.oldPower = this.power;
  }


  if (this.changeDetected) {
      this.noChangeCount = 0;
  } else {
      // log that hook was called when there was no relevant change.
      let count = this.noChangeCount += 1;
      let noChangeMsg = `DoCheck called ${count}x when no change to hero or power`;
      if (count === 1) {
        // add new "no change" message
        this.changeLog.push(noChangeMsg);
      } else {
        // update last "no change" message
        this.changeLog[this.changeLog.length - 1] = noChangeMsg;
      }
  }


  this.changeDetected = false;
}

這段代碼會(huì)檢查某些感興趣的值,捕獲并把它們當(dāng)前的狀態(tài)和之前的進(jìn)行比較。當(dāng) heropower 沒有實(shí)質(zhì)性變化時(shí),它就會(huì)在日志中寫一條特殊的信息,這樣你就能看到 DoCheck() 被調(diào)用的頻率。其結(jié)果很有啟發(fā)性。

雖然 ngDoCheck() 鉤子可以檢測(cè)出英雄的 name 何時(shí)發(fā)生了變化,但卻非常昂貴。無論變化發(fā)生在何處,每個(gè)變化檢測(cè)周期都會(huì)以很大的頻率調(diào)用這個(gè)鉤子。在用戶可以執(zhí)行任何操作之前,本例中已經(jīng)調(diào)用了20多次。

這些初始化檢查大部分都是由 Angular 首次在頁面的其它地方渲染不相關(guān)的數(shù)據(jù)觸發(fā)的。只要把光標(biāo)移動(dòng)到另一個(gè) <input> 就會(huì)觸發(fā)一次調(diào)用。其中的少數(shù)調(diào)用揭示了相關(guān)數(shù)據(jù)的實(shí)際變化情況。如果使用這個(gè)鉤子,那么你的實(shí)現(xiàn)必須非常輕量級(jí),否則會(huì)損害用戶體驗(yàn)。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)