组件之间的交互
1.通过输入型绑定把数据从父组件传到子组件
2.通过 setter 截听输入属性值的变化 -类似于vue的watch(监听单个(输入)属性的变化)
3.通过ngOnChanges()来截听输入属性值的变化-当需要监视多个、交互式输入属性的时候,本方法比用属性的 setter 更合适
4.父组件监听子组件的事件
5.父组件与子组件通过本地变量互动
6.父组件调用@ViewChild()
7.父组件和子组件通过服务来通讯
通过输入型绑定把数据从父组件传到子组件
-
关键词 @Input()
-
相关代码
import { Component, Input, OnInit } from '@angular/core'; interface Hero { id: number; name: string; } @Component({ selector: 'app-input-data-parent', template: ` <ul> <li *ngFor="let hero of heros; let key = index"> <app-input-data-chilren [name]="hero.name" [martek] = "martek" ></app-input-data-chilren> </li> </ul> `, }) export class InputDataParentComponent implements OnInit { heros: Hero[] = []; martek: string = 'market'; constructor() {} ngOnInit(): void { this.heros = [ { id: 0, name: 'hero-1', }, { id: 1, name: 'hero-2', }, { id: 2, name: 'hero-3', }, ]; } } @Component({ selector: 'app-input-data-chilren', template: ` <h1>{{ name }}----{{marketName}}</h1> `, }) export class InputDataChilrenComponent implements OnInit { @Input() name: string; @Input('martek') marketName:string constructor() {} ngOnInit(): void {} } }
通过 setter 截听输入属性值的变化
-
关键词 @Input() getXXX(){} setXXX(){} public _XXX = ‘’
-
相关代码
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'app-set-data-parent', template: ` <div> <app-set-data-chilren [martek]="martek"></app-set-data-chilren> <button (click)="increaseMarket()">change martek value</button> </div> `, }) export class SetDataParentComponent implements OnInit { martek: string = 'market'; constructor() {} ngOnInit(): void {} increaseMarket() { this.martek += '1'; } } @Component({ selector: 'app-set-data-chilren', template: ` <h1>{{ martek }}</h1> `, }) export class SetDataChilrenComponent implements OnInit { @Input() get martek(): string { return this._martek; } set martek(name: string) { // this._martek = name this.setMartek(name); } public _martek = ''; constructor() {} ngOnInit(): void {} setMartek(name: string) { console.log('name:', name); this._martek = '%%%%' + name; } }
3.该属性可以用于
通过ngOnChanges()来截听输入属性值的变化
-
关键词 SimpleChanges
-
相关代码
import { Component, Input, OnInit, SimpleChanges, } from '@angular/core'; @Component({ selector: 'app-onchanges-data-parent', template: ` <div> <app-onchanges-data-chilren [martek]="martek" [counter]="counter" ></app-onchanges-data-chilren> <button (click)="increaseMarket()">change martek value</button> <button (click)="increaseCounter()">change martek value</button> </div> `, }) export class ChangesDataParentComponent implements OnInit { martek: string = 'market'; counter: number = 0; constructor() {} ngOnInit(): void {} increaseMarket() { this.martek += '1'; } increaseCounter() { this.counter++; } } @Component({ selector: 'app-onchanges-data-chilren', template: ` <h1>{{ martek }}</h1> <h1>{{ counter }}</h1> <ul> <li *ngFor="let log of logs; let key = index"> {{ key + 1 }} --- {{ log }} </li> </ul> `, }) export class ChangesDataChilrenComponent implements OnInit { @Input() martek: string; @Input() counter: number; logs: string[] = []; constructor() {} ngOnInit(): void {} ngOnChanges(changes: SimpleChanges): void { console.log('changes:', changes); for (let key in changes) { if (!changes[key].firstChange) { const str = `key Changes 从${changes[key].previousValue} 变成了 ${changes[key].currentValue}`; this.logs.push(str); } } } }
父组件监听子组件的事件
-
关键词 @Output() addMartek = new EventEmitter() and 事件按绑定
-
相关代码
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-output-data-parent', template: ` <div> <app-output-data-chilren [martek]="martek" (addMartek)="addMartek($event)" ></app-output-data-chilren> </div> `, }) export class OutputDataParentComponent implements OnInit { martek: string = 'market'; constructor() {} ngOnInit(): void {} addMartek(value: string) { this.martek = value[0]; } } @Component({ selector: 'app-output-data-chilren', template: ` <h1>{{ martek }}</h1> <button (click)="changeMartek()">change martek <button></button></button> `, }) export class OutputDataChilrenComponent implements OnInit { @Input() martek: string; @Output() addMartek = new EventEmitter(); constructor() {} ngOnInit(): void {} changeMartek() { const myMarek: string[] = [this.martek + 1]; console.log('myMarek:', myMarek); this.addMartek.emit(myMarek); } }
父组件与子组件通过本地变量互动
-
关键词 模板上绑定子组件的引用
-
相关代码
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-local-data-parent', template: ` <div> <app-local-data-chilren #local ></app-local-data-chilren> <h1>{{ local.marktek }} ==== {{ local.counter }}</h1> <button (click)="local.newMarket()">change martek value</button> <button (click)="local.newCounter()">change counter value</button> </div> `, }) export class LocalDataParentComponent implements OnInit { constructor() {} ngOnInit(): void {} } @Component({ selector: 'app-local-data-chilren', template: ` <h5>{{ marktek }}</h5> <h5>{{ counter }}</h5> `, }) export class LocalDataChilrenComponent implements OnInit { ngOnInit(): void {} public marktek: number = 100; public counter: number = 2; newMarket() { this.marktek += 10; } newCounter() { this.counter++; } }
父组件调用@ViewChild()—本地变量的升级版
-
关键词 @ViewChild() ngAfterViewInit()
-
相关代码
import { Component, OnInit, AfterViewInit, ViewChild } from '@angular/core'; @Component({ selector: 'app-viewChild-data-chilren', template: ` <h5>{{ marktek }}</h5> <h5>{{ counter }}</h5> `, }) export class ViewChildDataChilrenComponent implements OnInit { ngOnInit(): void {} public marktek: number = 100; public counter: number = 2; newMarket() { this.marktek += 10; } newCounter() { this.counter++; } } @Component({ selector: 'app-viewChild-data-parent', template: ` <div> <app-viewChild-data-chilren></app-viewChild-data-chilren> <h1>{{ marktek }}</h1> <button (click)="parentMarket()">in parent change martek value</button> <button (click)="newMarket()">change martek value</button> <button (click)="newCounter()">change counter value</button> </div> `, }) export class ViewChildDataParentComponent implements AfterViewInit { // public marktek: number; get marktek() { return this._marktek; } set marktek(value: number) { this._marktek = this.local.marktek = value; } public _marktek: number; @ViewChild(ViewChildDataChilrenComponent) public local: ViewChildDataChilrenComponent; constructor() {} ngAfterViewInit() { // console.log('this.local:', this.local); setTimeout(() => { this.marktek = this.local.marktek; }, 0); } parentMarket() { this.marktek = 10000; // this.local.marktek = 10000; } newMarket() { this.local.newMarket(); } newCounter() { this.local.newCounter(); } }
-
注意事项
1.需要在 ngAfterViewInit() 生命周期函数中去获取子组件
2.在父组件中可以引用到子组件的属性和方法
3.在父组件中可以改变子组件的属性值和调用子组件的方法
4.注意父组件的视图更新,当父组件的属性错过此次checked之后改变的话需要setTimeout()等待下一轮视图更新
父组件和子组件通过服务来通讯
-
关键词 @ViewChild() ngAfterViewInit()
-
相关代码
/* @/src/app/service-data/service-data.service.ts */ import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; @Injectable() export class MessageService { // Observable string sources public messageService = new Subject<string>(); public initMessageService = new Subject<string>() // Observable string streams setMessage$ = this.messageService.asObservable(); initMessage$ = this.initMessageService.asObservable() // Service message commands setMessage(mission: string) { this.messageService.next(mission); } initMessage(astronaut: string) { this.initMessageService.next(astronaut); } } /* @/src/app/service-data/service-data.component.ts */ import { stringify } from '@angular/compiler/src/util'; import { Component, Input, OnInit } from '@angular/core'; import { MessageService } from './service-data.service'; @Component({ selector: 'app-service-data-parent', providers: [MessageService], template: ` <div> <app-service-data-chilren *ngFor="let child of childList; let key = index" [myObj]="child" [key]="key" ></app-service-data-chilren> <ul> <li *ngFor="let mes of messageList"> {{ mes }} </li> </ul> <button (click)="clear()">clear history</button> </div> `, }) export class ServiceDataParentComponent implements OnInit { public childList: any[] = [ { name: 'child-1', }, { name: 'child-2', }, { name: 'child-3', }, ]; public messageList: string[] = []; constructor(public messageService: MessageService) {} ngOnInit(): void { this.wathcAndGetMessageList(); } wathcAndGetMessageList() { this.messageService.setMessage$.subscribe((message) => { this.messageList.push(message); }); } clear() { this.messageList = []; this.messageService.initMessage('clear'); } } @Component({ selector: 'app-service-data-chilren', template: ` <h1>{{ myObj.name }} say</h1> <h3>I am {{ key + 1 }}</h3> <h2>{{ message }}</h2> <button (click)="set()">set history</button> `, }) export class ServiceDataChilrenComponent implements OnInit { @Input() myObj: any; @Input() key: number; public setMessage: any; public initMessage: any; public message: string = ''; constructor(public messageService: MessageService) {} ngOnInit(): void { this.watchSetMessage(); this.watchInitMessage(); } watchSetMessage() { this.setMessage = this.messageService.setMessage$.subscribe((message) => { this.message = message; }); } watchInitMessage() { this.initMessage = this.messageService.initMessage$.subscribe((message) => { this.message = ''; }); } set() { this.messageService.setMessage(`${this.myObj.name} set message`); } ngOnDestroy() { this.initMessage.unsubscribe(); this.setMessage.unsubscribe(); } }
-
注意事项
1.如果组件的生命周期与应用的生命周期不同,需要在 ngOnDestroy()中销毁,以免造成内存泄漏