constructor ngOnChanges ngOninit ngDoCheck * ngAfterContentInit * ngAfterContentChecked * ngAfterViewInit * ngAfterViewChecked ngOnDestroy
ngOnChangesapp
每一次
@Input
都會執行一次dom
ngOnInitide
初始化數據的加載函數
ngOnDestroythis
在原件銷燬以前spa
ngDoCheckcode
每一次執行變動,都會自動執行
ngDoCheck
事件blog
子元件事件token
ngAfterViewInit生命週期
- 當View裏面全部元件都初始化完成後 觸發的事件
ngAfterViewChecked
- 當view裏面全部元件都完成變動偵測機制後觸發的事件
ngAfterViewChecked 父組件裏面放入一個子組件,子組件裏面有個視圖改變操做 <input [(ngModel)]="hello"> hello = 'hello'; 咱們在父組件裏面監聽變化 ngAfterViewChecked() { console.log(1); } 咱們發現每次子組件input輸入的值發生變化的時候,ngAfterViewChecked 都會執行這樣寫好像沒什麼意義,那咱們能夠升級下寫法
父組件直接拿到變化的值 // 拿到子組件這個函數 @ViewChild(AComponent) a:AComponent ngAfterViewChecked() { console.log(this.a.hello); }
內容元件事件 ng-content
ngAfterContentInit
- 當content裏面全部的元件都初始化完成後觸發事件
<app-a> <app-b></app-b> </app-a>父
ng-content
把子組件的內容映射到父組件app-a <ng-content></ng-content> 內容投影 子 app-b 經過ng-content拿到子組件內容 父組件直接拿到<ng-content>的子組件 export class AComponent implements AfterContentInit{ @ContentChild(BComponent) B: BComponent; ngAfterContentInit() { console.log(this.B); } }ngAfterContentChecked
- 當content裏面全部元件都完成後偵測機制後觸發事件
ViewChild(selector: string | Function | Type<any>, opts: { read?: any; static: boolean; }): any
兩個參數,Aselector
和opts
selector
: 字符串,類型或者字符串或類型的函數,默認查找與選擇器匹配的第一個元素
opts
: 有兩個選項
static
肯定查找什麼時候解析,查詢指定的字符串解析,true
初始化視圖時,false
若是你但願在每次更改檢測後解決後解決它
獲取angular 組件內呈現的DOM元素的引用,能夠進行DOM元素的操做
<div #someElement>Sample Code</div> @ViewChild('someElement') some; ngAfterViewInit 生命週期能夠拿到這個引用 ngAfterViewInit(): void { this.some.nativeElement }
視圖查詢
@Component
或@Directive
裝飾器的類當前視圖使用的 @ViewChild(SomeService) someService: SomeService )
@ViewChild('someToken') someTokenVal: any
(剛開始我不懂,其實就是你子組件使用啦,就是可使用)@Directive({ selector: '[appDir]' , providers: [ {provide: 'token', useValue: 'test'}, {provide: TOKEN_URL, useValue: 'test1'}, TestOneService ] }) 頁面使用 <div appDir>dfsdsfdsfdsf</div> ts查找 @ViewChild('token',{static:true}) token:string; @ViewChild(TOKEN_URL,{static:true}) token1:any; @ViewChild(TestOneService) test:TestOneService; ngAfterViewInit() { console.log(this.token); console.log(this.token1); console.log(this.test); }
new(selector: Type<any>|InjectionToken<unknown>|Function|string, opts?: {descendants?: boolean, read?: any}): Query;
opts
區別
@ViewChildren
元素引用列表,而不是單個引用
<input type="text" [(ngModel)]="a"> <input type="text" [(ngModel)]="b"> <input type="text" [(ngModel)]="c"> a = 1 b = 2 c = 2; @ViewChildren(NgModel) model: QueryList<NgModel> ngAfterViewInit() { console.log(this.model.length);// 能夠拿到這三個值 }
<div appDir [dir]="['aaa']"></div> <div appDir [dir]="{sex:'男'}"></div> 父 @ViewChildren(DirDirective) directives!: QueryList<DirDirective>; ngAfterViewInit() { this.directives.forEach(val=>{ console.log(val); }) }
可能會對QueryList
返回的不怎麼理解
ViewChild和ViewChildren可用於訪問子組件的屬性和方法。使用ViewChild和ViewChildren,咱們能夠獲取子組件的引用,從而進一步提供對全部屬性和方法的訪問。這可使父組件訪問子組件並啓用它們之間的通訊。
父組件對子組件的值的修改 父 <button (click)="clickDown()">Click</button> <app-b #app></app-b> @ViewChild('app') app:BComponent; clickDown() { this.app.num=20; } 子 num=10
<app-a *ngFor="let config of configs" [config]="config"></app-a> configs = [ {opacity: 0, duration: 500}, {opacity: 1, duration: 600}, ]; 子 @Input('config') config;
<app-a #ccc></app-a> <app-b #ccc></app-b> 父 export class TwoComponent implements OnInit, AfterViewInit, AfterViewChecked,AfterContentInit { @ViewChild('ccc') C:AComponent; @ViewChildren('ccc') cRen:QueryList<AComponent|BComponent> constructor() {} ngAfterViewInit() { console.log(this.C);// 默認拿到第一個 console.log(this.cRen);//默認拿到兩個組件的集合 console.log(this.cRen.first); //拿到第一個 console.log(this.cRen.last);// 拿到最後一個 } ngOnInit(): void {} }
<p #ccc></p> <div #ccc></div> @ViewChild('ccc') C:ElementRef; @ViewChildren('ccc') cRen:QueryList<ElementRef> ngAfterViewInit() { console.log(this.C);// 默認拿到第一個 console.log(this.cRen.first); //拿到第一個 }
<p #ccc #aaa></p> @ViewChild('ccc') C:ElementRef; @ViewChild('aaa') A:ElementRef; ngAfterViewInit() { console.log(this.C);// 默認拿到第一個 console.log(this.A); } 同理 ViewChildren也是同樣的
用ViewContainerRef
填充到頁面
<ng-template #aaa> <h1>aaaa</h1> <h1>bbb</h1> </ng-template> @ViewChild('aaa') A: TemplateRef; constructor(private vRef: ViewContainerRef) { } ngAfterViewInit() { this.vRef.createEmbeddedView(this.A) }
<app-a #q> <app-b #contentQuery></app-b> <app-c #contentQuery></app-c> </app-a> 大盒子 @ViewChild('q') A:AComponent ngAfterViewInit() { console.log(this.A); } app-a <ng-content></ng-content> 怎麼拿到這兩個子組件的列表呢 @ContentChild(BComponent) B; @ContentChild(CComponent) C; @ContentChildren('contentQuery') D!:QueryList; ngAfterContentInit() { console.log(this.B); console.log(this.C); console.log(this.D); //拿到兩個啦 }
dom形式相似
<app-a> <div #contentQuery>xxx</div> <div #contentQuery>bbb</div> </app-a> app-a <ng-content></ng-content> @ContentChildren('contentQuery') contentQuery; ngAfterViewInit() { console.log(this.contentQuery); }
兩個要一塊兒用否則會報錯,也能夠直接使用set,也就是說get是可選的,可是set是必傳的
能夠拿到修改的記錄 <span #foo></span> _foo!: ElementRef; @ViewChild('foo') get foo(): ElementRef { return this._foo; } set foo(value: ElementRef) { this._foo = value; } ngAfterViewInit() { let text=this.renderer.createText('xxxx') this.renderer.appendChild(this._foo.nativeElement,text) }
指令
<div [appTestDir]="'aaa'"></div> export class TwoComponent implements OnInit, AfterViewInit, AfterViewChecked, AfterContentInit { _textDir!: TestDirDirective; @ViewChild(TestDirDirective, {static: true}) //true 初始化視圖時 get textDir(): TestDirDirective { return this._textDir; } set textDir(value: TestDirDirective) { console.log(value.appTestDir); //222 this._textDir = value; } ngAfterViewInit() { console.log(this._textDir.appTestDir);//aaa } }
<app-b [content]="app"></app-b> <ng-template #app> <app-a></app-a> </ng-template> app-b @Input('content') content; <ng-container *ngTemplateOutlet="content"></ng-container>
升級第二種方式
<app-a> <ng-template #contentQuery> <h1>dddddd</h1> </ng-template> <ng-template #contentQuery> <h1>ggggg</h1> </ng-template> </app-a> app-a <ng-content></ng-content> <!--第一個--> <div *ngTemplateOutlet="contentQuery.first"></div> @ContentChildren('contentQuery') contentQuery:QueryList<TemplateRef<any> | null>; ngAfterContentInit() { console.log(this.contentQuery); }
其實指令也是同理能夠拿到的
<sub-comp> <div some-dir></div> <div some-dir></div> </sub-comp> @Directive({selector: '[some-dir]'}) class SomeDir { } 大盒子能夠直接查到 @ViewChild(SubComp) subComp!: SubComp; sub-comp <ng-content></ng-content> @ContentChildren(SomeDir) foo!: QueryList<SomeDir>;
<app-a> <div *ngIf="showing" #cmp>h1 h1</div> </app-a> <button (click)="showing=!showing">++</button> showing: boolean=true; ==== app-a <ng-content></ng-content> @ContentChildren('cmp',{descendants:false}) cmp!:QueryList<ElementRef> ngAfterContentChecked() { console.log(this.cmp.length); }
另外一個方式
<button (click)="showing=!showing">++</button> <div *ngIf="showing" #foo> <h1>我是誰</h1> </div> @ViewChildren('foo') foos!: QueryList<any>; showing: boolean=true; ngAfterViewInit() { this.foos.changes.subscribe(value=>{ console.log(value); }) }