Angular組件——組件生命周期(一)

来源:https://www.cnblogs.com/starof/archive/2018/04/03/8641491.html
-Advertisement-
Play Games

組件聲明周期以及angular的變化發現機制 紅色方法只執行一次。 變更檢測執行的綠色方法和和組件初始化階段執行的綠色方法是一個方法。 總共9個方法。 每個鉤子都是@angular/core庫里定義的介面。 雖然介面不是必須的,Angular檢測到鉤子方法就會去執行它,還是建議把介面寫上。 一、鉤子 ...


組件聲明周期以及angular的變化發現機制 

 

紅色方法只執行一次。

變更檢測執行的綠色方法和和組件初始化階段執行的綠色方法是一個方法。

總共9個方法。

 每個鉤子都是@angular/core庫里定義的介面。

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-life',
  templateUrl: './life.component.html',
  styleUrls: ['./life.component.css']
})
export class LifeComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

雖然介面不是必須的,Angular檢測到鉤子方法就會去執行它,還是建議把介面寫上。

一、鉤子的調用順序

import { Component, OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy, Input, SimpleChange, SimpleChanges } from '@angular/core';

let logIndex: number = 1; //計數器

@Component({
  selector: 'app-life',
  templateUrl: './life.component.html',
  styleUrls: ['./life.component.css']
})
export class LifeComponent implements OnInit, OnChanges, DoCheck, AfterContentInit
  , AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy {
  @Input()
  name: string;

  logIt(msg: string) {
    console.log(`# ${logIndex++}  ${msg}`);
  }
  constructor() {
    this.logIt("name屬性在constructor里的值是: " + this.name);
  }

  ngOnInit() {
    this.logIt("name屬性在OnInit里的值是: " + this.name);
  }

  ngOnChanges(changes: SimpleChanges): void { // 傳入一個SimpleChanges對象
    let name = changes['name'].currentValue;
    this.logIt("name屬性在ngOnChanges里的值是: " + this.name);
  }

  ngDoCheck(): void {
    this.logIt("DoCheck");
  }

  ngAfterContentInit() {
    this.logIt("ngAfterContentInit");
  }

  ngAfterContentChecked() {
    this.logIt("ngAfterContentChecked");
  }

  ngAfterViewInit() {
    this.logIt("ngAfterViewInit");
  }

  ngAfterViewChecked() {
    this.logIt("ngAfterViewChecked");
  }
  ngOnDestroy() {
    this.logIt("ngOnDestory");
  }
}
View Code

初始化邏輯依賴輸入屬性的值時,初始化邏輯一定要寫在ngOnInit里,不能寫在constructor裡面。

DoCheck在Angular的每個變更檢測周期中調用。

ngAfterContentInit和ngAfterContentChecked跟模版,組件的內容投影相關的。

ngAfterViewInit和ngAfterViewChecked跟組件的模版,初始化視圖相關的。

二、onChanges鉤子

父組件初始化或修改子組件的輸入參數時會被調用。

需要先理解js中可變對象 和 不可變對象。

//字元串是不可變的
var greeting = "Hello";
greeting = "Hello World";
//對象是可變的
var user = { name: "Tom" };
user.name = "Jerry";

例子:

child組件有3個屬性,其中2個是輸入屬性。

 

父組件有一個greeting屬性和一個name屬性是Tom的user對象。

父組件要改變輸入屬性,所以greeting和user.name是雙向綁定。

<div class="parent">
    <h2>我是父組件</h2>
    <div>問候語:<input type="text" [(ngModel)]="greeting"></div>
    <div>
      姓名:
      <input type="text" [(ngModel)]="user.name">
    </div>
    <app-child [greeting]="greeting"  [(user)]="user"> </app-child>
</div>

父組件改變兩個input的值,值變化時候傳入子組件的值也會變化,傳入子組件的輸入屬性的值變化時會觸發ngOnChanges()。

父組件初始化子組件。初始化的時候調一次ngOnChanges(),初始化後子組件的greeting變成Hello,也就是父組件上的greeting的值。

user變成一個name屬性為Tom的對象。

改變輸入屬性的值,父組件問候語greeting改為Helloa。

Angular的變更檢測刷新不可變對象,也就是greeting的值,然後調用ngOnChanges()方法,greeting的值從之前的hello,變為了Helloa。

修改user.name為Tomb,控制臺上沒有列印新的消息。

因為用戶只是改變了可變對象user的屬性,user對象的引用自身是沒有改變的,所以onChanges()方法沒有被調用。

雖然可變對象的屬性改變不會觸發ngOnChanges()方法調用,但是子組件的user對象的屬性仍然改變了,由於Angular的變更監測機制仍然捕獲了組件中每個對象的屬性變化。

改變子組件的message屬性也不引起子組件的onChanges()方法調用。因為message不是輸入屬性。而ngOnChanges()只有在輸入屬性變化時候被調用。

三、變更檢測機制和DoCheck()鉤子

變更檢測由zone.js實現的。保證組件的屬性變化和頁面的變化同步。瀏覽器中發生的非同步事件(點擊按鈕,輸入數據,數據從伺服器返回,調用了setTimeout()方法)都會觸發變更檢測。

變更檢測運行時,檢測組件模版上的所有綁定關係,如果組件屬性被改變,與其綁定的模版相應區域可能需要更新。

註意:變更檢測機制只是將組件屬性的改變反應到模版上,變更檢測機制本身永遠不會改變組件屬性的值

兩種變更檢測策略。

  • Default   檢測到變化,檢查整個組件樹。
  • OnPush  只有當輸入屬性變化時,才去檢測該組件及其子組件。

Angular應用是一個以主組件為根的組件樹,每個組件都會生成一個變更檢測器,任何一個變更檢測器檢測到變化,zone.js就根據組件的變更檢查策略來檢測組件(也就是調doCheck()鉤子),來判斷組件是否需要更新它的模版。

DoCheck檢查是從根組件開始往下檢查所有的組件樹,不管變更發生在哪個組件。

例子:

監控user.name這種可變對象的屬性的改變。

在child中加一個oldUsername來存變更前的username,加一個changeDetected屬性標誌username是否發生變化,預設是false。 noChangeCount計數器預設是0。

import { Component, OnInit, Input, OnChanges, SimpleChanges, DoCheck } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit, OnChanges, DoCheck {

  @Input()
  greeting: string;

  @Input()
  user: { name: string };

  message: string = "初始化消息";
  oldUsername: string;
  changeDetected: boolean = false;
  noChangeCount: number = 0;

  constructor() { }

  ngOnInit() {
  }

  ngOnChanges(changes: SimpleChanges): void {
    console.log(JSON.stringify(changes, null, 2));
  }

  ngDoCheck() {
    if (this.user.name !== this.oldUsername) {
      this.changeDetected = true;
      console.log("DoCheck: user.name 從 " + this.oldUsername + "變為" + this.user.name);
      this.oldUsername = this.user.name;
    }
    if (this.changeDetected) {//變化來計數器清0
      this.noChangeCount = 0;
    } else {//沒變化
      this.noChangeCount++;
      console.log("DoCheck:user.name沒變化時ngDoCheck方法已經被調用" + this.noChangeCount + "次")
    }
    this.changeDetected = false;//最後不管變沒變標誌位複位
  }

}
View Code

頁面載入完成:user.name沒變化時DoCheck方法已經被調用1次。

滑鼠點擊,不改變任何值,點擊觸發變更檢測機制,所有組件的DoCheck就會被調用。

修改Tom為Tomb,DoCheck捕捉到Tom變為Tomb。

 雖然DoCheck()鉤子可以檢測到user.name什麼時候發生變化,但是使用必須小心,ngDoCheck()鉤子被非常頻繁的調用。每次變更檢測周期後發生變化的地方都會調用。

對ngDoCheck()的實現必須非常高效,非常輕量級,否則容易引起性能問題。

同理:所有帶Check關鍵字的鉤子方法都要非常小心。 ngDoCheck,ngAfterContentChecked,ngAfterViewChecked.

 

本文作者starof,因知識本身在變化,作者也在不斷學習成長,文章內容也不定時更新,為避免誤導讀者,方便追根溯源,請諸位轉載註明出處:http://www.cnblogs.com/starof/p/8641491.html  有問題歡迎與我討論,共同進步。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 蘋果在關於後臺模式的文檔中稱:“這個配置項應該儘可能少的使用,而且最好只給那些提供通知服務的應用使用。如果有在後臺運行的替代方法,就應該使用替代方法。比如,如果應用能使用顯著位置變化介面來接受位置變動事件的話,就不要將應用註冊為需要在後臺監控位置變化的應用。 這個配置項可選的值有:audio,loc ...
  • 經過進兩周的持續發酵,Facebook5000萬用戶數據泄露事件,已讓其處在輿論的風尖浪口。對於手機APP泄漏用戶個人隱私問題,再次受到人們的關註。對於這個問題,你會怎麼看? 隱私,即不願公開的個人信息,前幾日,百度CEO李彥巨集在某論壇上說了一段引發爭議的話:“假如他們願意用隱私交換便捷性或者效率的 ...
  • 要瞭解TextView對文本的繪製,那麼就需要瞭解Paint.FontMetircs。 官方對該類的解釋是:Class that describes the various metrics for a font at a given text size., 意思是說,這玩意兒是繪製文本內容時存儲該文 ...
  • RxJava2已經推出有一年半的時間,由於之前RxJava已經在現有項目中廣泛使用,而RxJava2在除了很多命名外並沒有太多革新,所以相信有很多人跟我一樣都還沒有升級. 隨著老版本漸漸的失去維護,更重要的是有一定時間允許我來做這個遷移,其實棄老從新一直都是程式員的喜好. ...
  • 其中有一個不太規則的label: image.png image.png 這個label頂部的兩個角是圓角,底部的兩個角是直角,底部還有一個小三角。 思路 CAShapeLayer聯合UIBezierPath畫一個不規則的layer作為label.layer的mask。 具體實現 1.自定義一個繼承 ...
  • 自定義封裝UITableView,更加簡潔高效,無需為了實現delegate增加膠水代碼,自帶下拉刷新上拉載入控制項 "項目倉庫地址" 歡迎互相交流學習,問題交流群群號:296406818 如何開始 "項目技術特點" "安裝方法" "框架用法" 代碼結構 "GYTableBaseView.h" "GY ...
  • bug的產生和修改 上周臨近周末休息的時候,一個同事跑過來了,對我說:“阿倫啊,有一個頁面出問題了,火狐瀏覽器所有的input都沒法輸入了。”我一聽,是不是你給加了什麼屬性,讓input輸入框只讀了啊。看了一下代碼,很正常的一個輸入框,並且CSS寫的也很正常。 但是運行之後發現無法輸入任何東西,包括 ...
  • 這一篇從最基礎的知識來瞭解Bootstrap. 雖然V4版本已經出來,但還是拿V3來做演示,因為V4我也沒用過 ~~ 官方中文文檔 ,寫的很詳細,但作為入門來說,我感覺不太友好 https://v3.bootcss.com/ 可視化佈局,可以方便的拿來官方文檔的例子,複製粘貼大法好 Bootstra ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...