angular 父子组件交互

发布于 2021-03-29  621 次阅读


angular NgModule

@Input装饰器

angular 通过 @Input 为组件提供输入。

import { Component,Input } from '@angular/core';
import { Hero } from './hero';

@Component({
    selector:'app-hero-child',
    template:`
        <h3>{{hero.name}} says:</h3>
        <p>I,{{hero.name}},am at your service,{{masterName}}</p>
    `
})
export class HeroChildComponent{
    @Input() hero:Hero;
    @Input('master') masteName:string;  # 为masterName指定一个别名
}

可以通过 setter 截听输入属性值的变化

import {Component,Input} from '@angular/core';

@Component({
    selector:'app-name-child',
    template:'<h3>{{name}}</h3>'
})
export class NameChildComponent{
    @Input()
    get name():string {return this._name;}
    set name(name:string) { # 对输入进行设置
        this._name = (name&&name.trim())||'<no name set>';
    }
    private _name='';
}
import { Component } from '@angular/core';

@Component({
    selector:'app-name-parent',
    template:`
        <h2>Master controls {{names.length}} names</h2>
        <app-name-child *ngFor='let name of names' [name]="name"></app-name-child>
    `
})
export class NameParentComponent {
    names = ['Dr IQ',' ',' Bombasto']
}

也可以用 ngOnChanges() 来截听输入属性值得变化

@Output装饰器

父组件监听子组件事件

子组件暴露一个 EventEmitter 属性,当事件发生时,子组件利用该属性向上 emit 事件。父组件绑定这个事件属性,并在事件发生时做出回应。
实际上使用 rxjs 会更加便利。
子组件的 EventEmitter 属性是一个输出属性,通常带有 @Output 装饰器。

import { Component,EventEmitter,Input,Output } from '@angular/core';

@Component({
    selector:'app-voter',
    template:`
    <h4>{{name}}</h4>
    <button (click)="vote(true)" [disabled]="didVote">Agree</button>
    <button (click)="vote(false)" [disabled]="didVote">Agree</button>
    `
})
export class VoterComponent {
    @Input() name:string;
    @Output() voted = new EventEmitter<boolean>();
    didVote = false;

    vote(agreed:boolean){
        this.voted.emit(agreed);
        this.didVote = true;
    }
}
import { Component } from '@angular/core';

@Component({
    selector:'app-vote-taker',
    template:`
    <h2>Should mankind colonize the Universe?</h2>
    <h3>Agree:{{agreed}},Disagree:{{disagreed}}</h3>
    <app-voter *ngFor="let voter of voters" [name]="voter" (voted)="onVoted($event)">
    </app-voter>
    `
})
export class VoteTakerComponent{
    agreed = 0;
    disagreed = 0;
    voters = ['Barco','Celeritas','Bombasto'];

    onVoted(agreed:boolean){
        agreed?this.agreed++:this,disagreed++;
    }
}

父组件与子组件通过本地变量互动

父组件不能使用数据绑定来读取子组件的属性或调佣子组件的方法。但可以在父组件的 模板(也就是html)中使用一个本地变量来代表子组件,然后利用这个变量来读取子组件的属性和调用子组件的方法。

import { Component,OnDestroy } from '@angular/core';

@Component({
    selector:'app-countdown-timer',
    template:'<p>{{message}}</p>'
})
export class CountdownTimerComponent implements OnDestroy{
    intervalId = 0;
    message = '';
    seconds = 11;

    ngOnDestroy(){
        this.clearTimer();
    }

    start(){
        this.countDown();
    }

    stop(){
        this.clearTimer();
        this.message = `Holding at T-{this.seconds} seconds`;
    }

    private clearTimer(){
        clearInterval(this.intervalId);
    }

    private countDown(){
        this.clearTimer();
        this.intervalId = window.setInterval(()=>{
            this.seconds -=1;
            if(this.seconds===0){
                this.message='Blast off!';
            }else{
                if(this.seconds<0){
                    this.seconds = 10;
                }
                this.message = `T-{this.seconds} seconds and counting`;
            }
        },1000);
    }
}
import { Component } from '@angular/core';
import { CountdownTimerComponent } from './countdown-timer.component';

@Component({
    selector:'app-countdown-parent-lv',
    template:`
    <h3>Countdown to Liftoff (via local variable)</h3>
    <button (click)="timer.start()">Start</button>
    <button (click)="timer.stop()">Stop</button>
    <div class="seconds">{{timer.seconds}}</div>
    <app-countdown-timer #timer></app-countdown-timer>
    `,
    styleUrls:['../assets/demo.cs']
})
export class CountdownLocalVarParentComponent{}

@ViewChild

@ViewChild 可以将 模板中的 子组件导入到 父组件内进行访问。@ViewChildren用于多个组件。

import { AfterViewInit,ViewChild,Component,CountdownTimerComponent } from '@angular/core';

@Component({
    selector:'app-countdown-parent-vc',
    template:`
    <h3>Countdown to Liftoff (via ViewChild)</h3>
    <button (click)="start()">Start</button>
    <button (click)="stop()">Stop</button>
    <div class="seconds>{{seconds()}}</div> <!--可以用函数-->
    <app-countdown-timer></app-countdown-timer>
    `,
    styleUrls:['../assets/demo.css']
})
export class CountdownViewChildParentComponent implements AfterViewInit{
    @ViewChild(CountdownTimerComponent)
    private timerComponent:CountdownTimerComponent;

    seconds() {return 0;}

    ngAfterViewInit(){
        setTimeOut(()=>this.seconds=()=>this.timerComponent.seconds,0); # 直接赋值函数
    }

    start(){this.timerComponent.start();}
    stop(){this.timerComponent.stop();}
}

朝闻道,夕死可矣