angular6.x--父子组件通信

2020-05-17  本文已影响0人  Sun____

demo文档结构:

image.png
>父组件给子组件传值
首先在父组件所在在模块中引入子组件
import {RecConnectComponent} from './components/rec-connect/rec-connect.component';

declarations: [ ...RecConnectComponent],

父组件
Html文件:

<app-header [getParentMsg]="parentMsg"></app-header>    //父组件调用子组件

.ts文件

export class AppComponent {
  public parentMsg='我是一条来自父组件的消息';
}

子组件(app-header)
.ts文件:

import { Component, OnInit ,Input} from '@angular/core';
export class HeaderComponent implements OnInit {
  @Input()  getParentMsg:string;//接收父组件传过来的值 getParentMsg可以直接用
}

>子组件给父组件传值
子组件
.ts文件

//子组件引入Output 和 EventEmitter
import { Component, OnInit ,Output,EventEmitter} from '@angular/core';
let sonMsg = '我是一条来自子组件的消息';
export class HeaderComponent implements OnInit {
    //子组件中实例化 EventEmitter
    @Output() private toParent = new EventEmitter<string>();   
    /*用EventEmitter 和output装饰器配合使用  <string>指定类型变量*/
    public anotherSonMsg = '子组件传来的第二条消息';
    ngOnInit() { 
        this.sendParent();
    }
    sendParent(){
        this.toParent.emit(`${sonMsg};${this.anotherSonMsg}`);
        //子组件通过  EventEmitter 对象outer实例广播数据
    }
}

父组件
.html文件

<app-header (toParent)="getMsg($event)"></app-header>

.ts文件

export class AppComponent {
//子组件toParent调用的时候,getMsg函数就会被调用
  getMsg(msg:string){
    console.log('父子传值:',msg);
  }
}

>父子组件动态交互
子组件接收父组件的数据,可以拦截属性的数据并进行相应的处理。
拦截有两种方式:
**1. setter拦截输入属性 **

private _name:Array<string>;
@Input()
//getParentMsg:string;//接收父组件传过来的值
set getParentMsg(name:Array<string>){
  this._name = name.map((val)=>(val&&val.trim() || '未定义名称'));
}
get getParentMsg(){return this._name}

打印getParentMsg得到的值:["我是一条来自父组件的消息", "Mr. IQ", "未定义名称", "Bombasto"]
**2. ngOnChanges监听数据变化 **
ngOnChanges监听数据绑定中发生的数据变化,该方法接收一个对象参数,包含当前值和变化前的值。

//引入OnChanges、SimpleChange
import { Component, OnChanges, SimpleChange,OnInit ,Input,Output,EventEmitter} from '@angular/core';
export class HeaderComponent implements OnInit {
  @Input()getParentMsg:Array<string>;//接收父组件传过来的值
  //ngOnChanges监听数据变化  处理父组件传值
  ngOnChanges(changes:{[propKey: string]: SimpleChange}){
    console.log('ngOnChanges监听数据变化:',changes);
    if(changes['getParentMsg']){
      let msg:Array<string> = changes['getParentMsg'].currentValue;
      this.getParentMsg = msg.map((val)=>(val&&val.trim() || '未定义名称'));
    }
  }
}

changes = {
  getParentMsg: {
    currentValue: ["  来自父组件的消息  ", "Mr. IQ", "   ",Bombasto  "],
    previousValue: {}
  }
}

4.父组件与子组件通过本地变量互动
父组件
.ts文件 引入子组件类

import { HeaderComponent }  from './components/header/header.component';

.html文件

<app-header #timer></app-header>
<button (click)="timer.start(timer.getParentMsg)">测试标签</button>
<button (click)="timer.stop()" >测试标签</button>

把本地变量(#timer)放到(app-header)标签中,用来代表子组件。这样父组件的模板就得到了子组件的引用,于是可以在父组件的模板中访问子组件的所有属性和方法

子组件
.ts文件

export class HeaderComponent implements OnInit {
 public getParentMsg:string = '子组件的值';
  start(msg) { alert(msg)}
  stop()  {alert('stop')}
}

这个本地变量方法是个简单便利的方法。但是它也有局限性,因为父组件-子组件的连接必须全部在父组件的模板中进行。父组件本身的代码对子组件没有访问权。
5.父组件调用@ViewChild() 调用子组件方法和属性
父组件
.ts文件:

import { ViewChild } from '@angular/core';
import { HeaderComponent }  from './components/header/header.component';
@ViewChild(HeaderComponent)
private getSonData: HeaderComponent;
showSonData(){
  this.getSonData.start(this.getSonData.getParentMsg);
}

6.通过服务通信
服务 my-data.service.ts

export class MyDataService {
//父子组件通过服务通信
  private parMsg = new Subject<string>();
  private sonMsg = new Subject<string>();
  parMsg$ = this.parMsg.asObservable();
  sonMsg$ = this.sonMsg.asObservable();

  parMsgs(msg:string){
    this.parMsg.next(msg);
  }
  sonMsgs(msg:string){
    this.sonMsg.next(msg);
  }
}

数据流程图:
组件触发数据改变-->调用服务的函数(parMsgs || sonMsgs),并把改变数据作为参数传递过去-->服务的asObservable()广播改变-->组件通过订阅(parMsg$ || sonMsg$)得到改变数据

父组件 app.component.ts

//导入服务
import { MyDataService } from './my-data.service';
export class AppComponent {
  servMsg = '这是通过服务实现父子组件通信的';
  constructor(private myDataService: MyDataService) {
    myDataService.sonMsg$.subscribe(
      val=> {
        this.servMsg = val;
      });
  }
  servMsgChgP(){
    this.servMsg = '父组件传递数据';
    this.myDataService.parMsgs(this.servMsg);
  };
}

.html

<button (click)="servMsgChgP()">{{servMsg}}</button>

子组件 header.component.ts

//导入服务
import { MyDataService } from './../../my-data.service';
import { Subscription }   from 'rxjs/Subscription';
subscription: Subscription;
servMsg:string= '父子组件传递数据';
constructor(private location:Location,private router:Router,private myDataService: MyDataService) {
  this.subscription = myDataService.parMsg$.subscribe(
    val=> {
      this.servMsg = val;
    });
}
servMsgChgS(){
  this.servMsg = '子组件传递数据';
  this.myDataService.sonMsgs(this.servMsg);
}

.html

<li><a (click)="servMsgChgS()">{{servMsg}}</a></li>

这样就实现了通过服务来实现父子组件通信;
此外其组件也可以订阅值改变的通知:
Home.component.ts

//导入服务
import { MyDataService } from './../../my-data.service';
import { Subscription }   from 'rxjs/Subscription';
export class HomeComponent implements OnInit {
  msg:string = '22222';
  subscription: Subscription;
  constructor(private myDataService: MyDataService) {
    this.subscription = myDataService.parMsg$.subscribe(
      val=> {
        this.msg = val;
      });
    myDataService.sonMsg$.subscribe(
      val=> {
        this.msg = val;
      });
  }
}

.html

<span>{{msg}}</span>
上一篇下一篇

猜你喜欢

热点阅读