在前端性能优化中有一条较大的条列是“减少交互/请求次数”;
简单的理解就是除了必要的http请求外,不进行请求能够很大程度上提升前端的响应速度以及流畅度; 随着组件化的出现,数据渲染页面已经逐步取代了由jsp到jQ操作DOM的方式;
组件通信,简单翻译为:在不同组件中传递和处理数据的方法;
常见的有父传子,子传父,兄弟通信(同级不相关);
本文介绍的通信方式如下: 1.Input 2.Output 3.子获父实例 4.父获子实例 5.Service层 6.EventEmitter 7.订阅
###1.父→子 input
parent.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
i: any = 0 ;
constructor(){
setInterval(() => {
this.i++;
}, 1000);
}
}
parent.html
<div>
<span>Parent</span>
</div>
<div>
<child-component [conent]="i"></child-component>
</div>
child.ts
import {Component, Input} from '@angular/core';
@Component({
selector: 'child-component',
templateUrl: './child-component.html',
styleUrls: []
})
export class childComponent {
@Input() conent: any;
constructor(){
}
}
child.html
<div>
<span>{{conent}}</span>
</div>
###2.子→父 output
parent.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
sum: any = 0;
getChildSum(sum: any) {
this.sum = sum;
}
}
parent.html
<div>
<span>Parent</span>
<span>{{sum}}</span>
</div>
<div>
<child-component (sendSum)="getChildSum($event)"></child-component>
</div>
child.ts
import {Component, EventEmitter, Output} from '@angular/core';
@Component({
selector: 'child-component',
templateUrl: './child-component.html',
styleUrls: []
})
export class childComponent {
btn: boolean = true;
@Output() sendSum: EventEmitter<any> = new EventEmitter();
sum: any = 0;
constructor() {
}
onStart(): void {
this.btn = false;
setInterval(() => {
this.sendSum.emit(++this.sum);
}, 1000);
}
}
child.html
<div>
<button (click)="onStart()" *ngIf="btn">点击开始</button>
</div>
###3.子获得父实例
parent.ts
@Component({
selector: 'page-parent',
templateUrl: 'parent.html',
})
export class ParentPage {
i:number = 0;
}
parent.html
<ion-header>
<ion-navbar>
<ion-title>Parent</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h1>parent: {{i}}</h1>
<page-child></page-child>
</ion-content>
child.ts
import { Component, Input, EventEmitter, Output,Host,Inject,forwardRef } from '@angular/core';
import{ParentPage} from '../parent/parent';
@Component({
selector: 'page-child',
templateUrl: 'child.html',
})
export class ChildPage {
constructor( @Host() @Inject(forwardRef(() => ParentPage)) app: ParentPage) {
setInterval(() => {
app.i++;
}, 1000);
}
}
child.html
<ion-content padding>
child
</ion-content>
###4.父获得子实例
parent.ts
import {ViewChild, Component } from '@angular/core';
import{ChildPage}from '../child/child';
@Component({
selector: 'page-parent',
templateUrl: 'parent.html',
})
export class ParentPage {
@ViewChild(ChildPage) child:ChildPage;
ngAfterViewInit() {
setInterval(()=> {
this.child.i++;
}, 1000)
}
}
parent.html
<ion-header>
<ion-navbar>
<ion-title>Parent</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h1>parent {{i}}</h1>
<page-child></page-child>
</ion-content>
child.ts
import { Component, Input, EventEmitter, Output,Host,Inject,forwardRef } from '@angular/core';
@Component({
selector: 'page-child',
templateUrl: 'child.html',
})
export class ChildPage {
i:number = 0;
}
child.html
<ion-content padding>
<h2>child {{i}}</h2>
</ion-content>
###5.service
parent.ts
import { Component } from '@angular/core';
import{myService}from '../child/myService'
@Component({
selector: 'page-parent',
templateUrl: 'parent.html',
})
export class ParentPage {
i:number=0;
constructor(service:myService) {
setInterval(()=> {
service.i++;
}, 1000)
}
}
parent.html
<ion-header>
<ion-navbar>
<ion-title>Parent</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h1>parent {{i}}</h1>
<page-child></page-child>
</ion-content>
child.ts
import { Component} from '@angular/core';
import{myService}from "../child/myService"
@Component({
selector: 'page-child',
templateUrl: 'child.html',
})
export class ChildPage {
constructor(public service:myService){
}
}
child.html
<ion-content padding>
<h2>child {{service.i}}</h2>
</ion-content>
myService.ts ps:记得在app.module.ts 加上providers: [KmyService]
import{Injectable } from '@angular/core';
@Injectable()
export class KmyService {
i:number = 0;
}
###6.EventEmitter
myService.ts
import {Component,Injectable,EventEmitter} from '@angular/core';
@Injectable()
export class myService {
change: EventEmitter<number>;
constructor(){
this.change = new EventEmitter();
}
}
parent.ts
import { Component } from '@angular/core';
import{myService}from '../child/myService'
@Component({
selector: 'page-parent',
templateUrl: 'parent.html',
})
export class ParentPage {
i:number = 0;
constructor(service:myService) {
setInterval(()=> {
service.change.emit(++this.i);
}, 1000)
}
}
parent.html
<ion-header>
<ion-navbar>
<ion-title>Parent</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h1>parent {{i}}</h1>
<page-child></page-child>
</ion-content>
child.ts
import { Component, EventEmitter} from '@angular/core';
import{myService}from "../child/myService"
@Component({
selector: 'page-child',
templateUrl: 'child.html',
})
export class ChildPage {
i:number = 0;
constructor(public service:myService){
service.change.subscribe((value:number)=>{
this.i = value;
})
}
}
child.html
<ion-content padding>
<h2>child {{i}}</h2>
</ion-content>
###7.订阅
parent.ts
import { Component } from '@angular/core';
import{myService}from '../child/myService'
@Component({
selector: 'page-parent',
templateUrl: 'parent.html',
})
export class ParentPage {
i:number=0;
constructor(public service:myService) {
setInterval(()=> {
this.service.StatusMission(this.i++);
}, 1000)
}
}
parent.html
<ion-header>
<ion-navbar>
<ion-title>Parent</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<h1>parent</h1>
<page-child></page-child>
</ion-content>
child.ts
import { Component, Injectable } from '@angular/core'
import { myService } from "../child/myService"
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'page-child',
templateUrl: 'child.html',
})
export class ChildPage {
i:number=0;
subscription: Subscription;
constructor(private Service: myService) {
this.subscription = Service.Status$.subscribe(message => {
this.i=message;
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
child.html
<ion-content padding>
<h2>child {{i}}</h2>
</ion-content>
myService.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class myService {
private Source=new Subject<any>();
Status$=this.Source.asObservable();
StatusMission(message: any) {
this.Source.next(message);
}
}
本篇借鉴相关图片及部分代码,侵权即删
=======================分割线=======================
补充 - 子组件向父组件传值思路, - 核心:@Input - 思路:通过@Input在子组件中引用父组件的fn,并将子组件的值作为参数传入父组件方法,当子组件调用父组件时自然获取到了子组件的值。(思考弊端:父组件直接调用该方法时理论上会报错,同时子组件杂糅过多业务层逻辑,依赖父组件方法增加耦合,都是一定弊病)