1. 使用指令来监视 DOM
可以深入了解你无法直接修改的 DOM 对象。你无法触及内置
的实现,也无法修改第三方组件,但是可以用指令来监视这些元素。
你可以把这个侦探指令写到任何内置元素或组件元素上,以观察它何时被初始化和销毁。
app.module.ts
表单要加入FormsModule, 引入自定义指令SpyDirective
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { Child1Component } from './components/father/components/child1/child1.component';
import { Child2Component } from './components/father/components/child2/child2.component';
import { FatherComponent } from './components/father/father.component';
import {ButtonModule} from 'primeng/button';
import { SpyComponent } from './components/father/components/spy/spy.component';
import { FormsModule } from '@angular/forms';
import { SpyDirective } from './directives/spy.directive';
import { CounterParentComponent } from './components/father/components/counter-parent/counter-parent.component';
import { CounterComponent } from './components/father/components/counter/counter.component';
@NgModule({
declarations: [
AppComponent,
FatherComponent,
Child1Component,
Child2Component,
SpyComponent,
SpyDirective,
CounterParentComponent,
CounterComponent
],
imports: [
BrowserModule,
HttpClientModule,
ButtonModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
father.component.html
<app-spy></app-spy>
spy.directive.ts
import { Directive, OnDestroy, OnInit } from '@angular/core';
let nextId = 1;
@Directive({
selector: '[appSpy]'
})
export class SpyDirective implements OnInit, OnDestroy {
private id = nextId++;
constructor() { }
ngOnInit() {
console.log(`spy-direcitve ngOnInit:${this.id}`);
}
ngOnDestroy() {
console.log(`spy-direcitve ngOnDestroy:${this.id}`);
}
}
spy.component.html
<div>
<h1>Spy Directive</h1>
<label>Hero name:</label>
<input type="text" [(ngModel)]="newName" (keyup.enter)="addHero()"/>
<button pButton type="button" (click)="addHero()">Add Hero</button>
<button pButton type="button" class="p-button-outlined" (click)="reset()">Reset Heroes</button>
<p *ngFor="let hero of heroes" appSpy>
{{hero}}
</p>
</div>
spy.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-spy',
templateUrl: './spy.component.html',
styleUrls: ['./spy.component.css']
})
export class SpyComponent implements OnInit {
public newName:string = "";
public heroes: string[] = ['hero1', 'hero2']
constructor() { }
ngOnInit() {
console.log(`app-spy: ngOnInit`);
}
addHero() {
console.log('addHero')
if(this.newName.trim()) {
this.heroes.push(this.newName.trim())
this.newName = '';
}
console.log(this.heroes);
}
removeHero(hero:string) {
this.heroes.splice(this.heroes.indexOf(hero), 1)
}
reset() {
this.heroes = [];
}
}
运行结果:
2. 同时使用组件和指令的钩子
在这个例子中,CounterComponent 使用了 ngOnChanges() 方法,以便在每次父组件递增其输入属性 counter 时记录一次变更。 这个例子将前例中的 SpyDirective 用于 CounterComponent 的日志,以便监视这些日志条目的创建和销毁。
father.component.html
<app-counter-parent></app-counter-parent>
counter-parent.component.html
<div>
<h2>Counter Spy</h2>
<button pButton type="button" (click)="updateCounter()">Update Counter</button>
<button pButton type="button" class="p-button-outlined" (click)="reset()">Reset Counter</button>
<app-counter [counter]="value"></app-counter>
</div>
counter-parent.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-counter-parent',
templateUrl: './counter-parent.component.html',
styleUrls: ['./counter-parent.component.css']
})
export class CounterParentComponent implements OnInit {
public value: number = 0;
constructor() { }
ngOnInit() {
console.log(`app-counter-parent ngOnInit`)
}
updateCounter() {
this.value += 1;
console.log(`value: ${this.value}`);
}
reset() {
this.value = 0;
console.log(`value: ${this.value}`);
}
}
counter.component.html
<div>
<p>Counter: {{counter}}</p>
<div>
<h3>Counter Change Log</h3>
<div *ngFor="let chg of changeLog" appSpy >{{chg}}</div>
</div>
</div>
counter.component.ts
import { Component, Input, OnInit, SimpleChanges } from '@angular/core';
@Component({
selector: 'app-counter',
templateUrl: './counter.component.html',
styleUrls: ['./counter.component.css']
})
export class CounterComponent implements OnInit {
@Input() counter:number = 0;
public changeLog: string[] = [];
constructor() { }
ngOnInit() {
console.log(`app-counter ngOnInit`)
}
ngOnChanges(changes: SimpleChanges): void {
const changeCounter = changes['counter'];
const changeCounterCurrent = changeCounter.currentValue;
const changeCounterPervious = changeCounter.previousValue;
this.changeLog.push(`counter: currentValue = ${changeCounterCurrent}, previousValue = ${changeCounterPervious}`)
if(this.counter === 0) this.changeLog = [];
}
}
运行结果:
3. 学习地址
Angular官网
|