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); }) }