这节咱们主要学习。Angular的钩子。他是伴随着Angular的生命周期存在的。下面咱们就来介绍Angular中有那些钩子api
钩子sass |
用途及时机app |
---|---|
|
当 Angular(从新)设置数据绑定输入属性时响应。 该方法接受当前和上一属性值的 当被绑定的输入属性的值发生变化时调用,首次调用必定会发生在 |
|
在 Angular 第一次显示数据绑定和设置指令/组件的输入属性以后,初始化指令/组件。3d 在第一轮 |
|
检测,并在发生 Angular 没法或不肯意本身检测的变化时做出反应。 在每一个 Angular 变动检测周期中调用, |
|
当把内容投影进组件以后调用。 第一次 |
每次完成被投影组件内容的变动检测以后调用。
|
|
|
初始化完组件视图及其子视图以后调用。 第一次 |
每次作完组件视图和子视图的变动检测以后调用。
|
|
|
当 Angular 每次销毁指令/组件以前调用并清扫。 在这儿反订阅可观察对象和分离事件处理器,以防内存泄漏。 在 Angular 销毁指令/组件以前调用。 |
从上面的表格能够看出ngOnChanges() 发生在因此变化以前。
值得注意的是。当咱们传入的类,而且改变类中的属性值。Angular并无作出改变。应为Angular认为类做为引用类型。他的引用地址并无发生改变。
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}`); } }
只有相对较少的调用才是因为对相关数据的修改而触发的。 显然,咱们的实现必须很是轻量级,不然将损害用户体验.
@Component({
selector: 'app-heroes',
templateUrl: '<after-content>
<app-child></app-child>
</after-content>',//
styleUrls: ['./heroes.component.sass']
})
@Component({ selector: 'app-heroes', templateUrl: '<div>-- child view begins --</div> <app-child-view></app-child-view> <div>-- child view ends --</div>',// styleUrls: ['./heroes.component.sass'] })
AfterContent 钩子和 AfterView 类似。关键的不一样点是子组件的类型不一样。
AfterView 钩子所关心的是 ViewChildren,这些子组件的元素标签会出如今该组件的模板里面。
AfterContent 钩子所关心的是 ContentChildren,这些子组件被 Angular 投影进该组件中。
AfterContent 钩子基于子级内容中值的变化而采起相应的行动,它只能经过带有@ContentChild装饰器的属性来查询到“子级内容”。
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(); } } // ... }
使用 AfterContent 时,无需担忧单向数据流规则
该组件的 doSomething()
方法当即更新了组件被绑定的 comment
属性。 它不用等下一回合。
Angular 在每次调用 AfterView 钩子以前也会同时调用 AfterContent。 Angular 在完成当前组件的视图合成以前,就已经完成了被投影内容的合成。 因此你仍然有机会去修改那个视图
咱们新建一个新的Component,来观察一个全新的Component调用了哪些钩子。
ngOnChanges() {
console.log('ngOnChanges is invoded.'); } ngOnInit() { console.log('ngOnInit is invoked.'); } ngDoCheck() { console.log('ngDoCheck is invoked'); } ngAfterContentInit() { console.log('ngAfterContentInit is invoked'); } ngAfterContentChecked() { console.log('ngAfterContentChecked is invoked'); } ngAfterViewInit() { console.log('ngAfterViewInit is invoked'); } ngAfterViewChecked() { console.log('ngAfterViewChecked is invoked'); } ngOnDestroy() { console.log('ngOnDestroy is invoked'); }
咱们能够看到ngOnInit 调用,ngDoCheck(+2),ngAfterContentInit和ngAfterContentChecked (+1),ngAfterViewInit和ngAfterViewChecked(+1),
可是咱们发现ngAfterContentChecked,和ngAfterViewChecked被单独各调用了一次。这是很意外的事情。
咱们new一个Hero对象。并把name属性绑定到input中。
咱们发现当修改那么属性的值。Angular都会调用, doCheck,afterContent,afterView,
这就能够理解当Component加载之初的最后三个钩子的调用,是做为对Component的check。
接着咱们给Component添加一个输入参数@Input,当咱们在Parent Component中修改Input的值的时候。onChange钩子被调用。
@Input() size: number; ngOnChanges(size) { console.log('ngOnChanges is invoded.'); }
咱们能够看到onChange子和以前的三个check的钩子一块儿被调用。