Angular学习笔记之-3.组件之间的交互

组件之间的交互

1.通过输入型绑定把数据从父组件传到子组件
2.通过 setter 截听输入属性值的变化 -类似于vue的watch(监听单个(输入)属性的变化)
3.通过ngOnChanges()来截听输入属性值的变化-当需要监视多个、交互式输入属性的时候,本方法比用属性的 setter 更合适
4.父组件监听子组件的事件
5.父组件与子组件通过本地变量互动
6.父组件调用@ViewChild()
7.父组件和子组件通过服务来通讯

通过输入型绑定把数据从父组件传到子组件

  1. 关键词 @Input()

  2. 相关代码

        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 截听输入属性值的变化

  1. 关键词 @Input() getXXX(){} setXXX(){} public _XXX = ‘’

  2. 相关代码

        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()来截听输入属性值的变化

  1. 关键词 SimpleChanges

  2. 相关代码

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

父组件监听子组件的事件

  1. 关键词 @Output() addMartek = new EventEmitter() and 事件按绑定

  2. 相关代码

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

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

  1. 关键词 模板上绑定子组件的引用

  2. 相关代码

        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()—本地变量的升级版

  1. 关键词 @ViewChild() ngAfterViewInit()

  2. 相关代码

        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();
        }
        }
    
    
  3. 注意事项
    1.需要在 ngAfterViewInit() 生命周期函数中去获取子组件
    2.在父组件中可以引用到子组件的属性和方法
    3.在父组件中可以改变子组件的属性值和调用子组件的方法
    4.注意父组件的视图更新,当父组件的属性错过此次checked之后改变的话需要setTimeout()等待下一轮视图更新

父组件和子组件通过服务来通讯

  1. 关键词 @ViewChild() ngAfterViewInit()

  2. 相关代码

    
        /* @/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();
        }
    }
    
    
  3. 注意事项
    1.如果组件的生命周期与应用的生命周期不同,需要在 ngOnDestroy()中销毁,以免造成内存泄漏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值