视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
对angular的组件通信的解析
2020-11-27 19:33:44 责编:小采
文档
 这篇文章主要介绍了关于对angular的组件通信的解析,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

单页面应用组件通信有以下几种,这篇文章主要讲 Angular 通信

  1. 父组件 => 子组件

  2. 子组件 => 父组件

  3. 组件A = > 组件B

父组件 => 子组件子组件 => 父组件sibling => sibling
@input@output
setters (本质上还是@input)注入父组件
ngOnChanges() (不推荐使用)

局部变量

@ViewChild()

serviceserviceservice
Rxjs的ObservalbeRxjs的ObservalbeRxjs的Observalbe
localStorage,sessionStoragelocalStorage,sessionStoragelocalStorage,sessionStorage

上面图表总结了能用到通信方案,期中最后3种,是通用的,angular的组件之间都可以使用这3种,其中Rxjs是最最牛逼的用法,甩redux,promise,这些同样基于函数式的状态管理几条街,下面一一说来

父组件 => 子组件

@input,最常用的一种方式

@Component({
 selector: 'app-parent',
template: '<p>childText:<app-child [textContent] = "varString"></app-child></p>',
 styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {
 varString: string;
 constructor() { }
 ngOnInit() {
 this.varString = '从父组件传过来的' ;
 }
}
import { Component, OnInit, Input } from '@angular/core';
@Component({
 selector: 'app-child',
 template: '<h1>{{textContent}}</h1>',
 styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
 @Input() public textContent: string ;
 constructor() { }
 ngOnInit() {
 }
}

setter

setter 是拦截@input 属性,因为我们在组件通信的时候,常常需要对输入的属性处理下,就需要setter了,setter和getter常配套使用,稍微修改下上面的child.component.ts
child.component.ts

import { Component, OnInit, Input } from '@angular/core';
@Component({
 selector: 'app-child',
 template: '<h1>{{textContent}}</h1>',
 styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
_textContent:string;
 @Input()
 set textContent(text: string){
 this._textContent = !text: "啥都没有给我" ? text ;
 } ;
 get textContent(){
 return this._textContent;
 }
 constructor() { }
 ngOnInit() {
 }
}

onChange

这个是通过angular生命周期钩子来检测,不推荐使用,要使用的话可以参angular文档

@ViewChild()

@ViewChild() 一般用在调用子组件非私有的方法

 import {Component, OnInit, ViewChild} from '@angular/core';
 import {ViewChildChildComponent} from "../view-child-child/view-child-child.component";
 @Component({
 selector: 'app-parent',
 templateUrl: './parent.component.html',
 styleUrls: ['./parent.component.css']
 })
 export class ParentComponent implements OnInit {
 varString: string;
 @ViewChild(ViewChildChildComponent)
 viewChildChildComponent: ViewChildChildComponent;
 constructor() { }
 ngOnInit() {
 this.varString = '从父组件传过来的' ;
 }
 clickEvent(clickEvent: any) {
 console.log(clickEvent);
 this.viewChildChildComponent.myName(clickEvent.value);
 }
 }
 import { Component, OnInit } from '@angular/core';
 @Component({
 selector: 'app-view-child-child',
 templateUrl: './view-child-child.component.html',
 styleUrls: ['./view-child-child.component.css']
 })
 export class ViewChildChildComponent implements OnInit {
 constructor() { }
 name: string;
 myName(name: string) {
 console.log(name);
 this.name = name ;
 }
 ngOnInit() {
 }
 }

局部变量

局部变量和viewChild类似,只能用在html模板里,修改parent.component.html,通过#viewChild这个变量来表示子组件,就能调用子组件的方法了.

<p class="panel-body">
 <input class="form-control" type="text" #viewChildInputName >
 <button class=" btn btn-primary" (click)="viewChild.myName(viewChildInputName.value)">局部变量传值</button>
 <app-view-child-child #viewChild></app-view-child-child>
 </p>

child 组件如下

@Component({
 selector: 'app-view-child-child',
 templateUrl: './view-child-child.component.html',
 styleUrls: ['./view-child-child.component.css']
})
export class ViewChildChildComponent implements OnInit {

 constructor() { }
 name: string;
 myName(name: string) {
 console.log(name);
 this.name = name ;
 }
 ngOnInit() {
 }

}

子组件 => 父组件

@output()

output这种常见的通信,本质是给子组件传入一个function,在子组件里执行完某些方法后,再执行传入的这个回调function,将值传给父组件

parent.component.ts
@Component({
 selector: 'app-child-to-parent',
 templateUrl: './parent.component.html',
 styleUrls: ['./parent.component.css']
})
export class ChildToParentComponent implements OnInit {

 childName: string;
 childNameForInject: string;
 constructor( ) { }
 ngOnInit() {
 }
 showChildName(name: string) {
 this.childName = name;
 }
}

parent.component.html

<p class="panel-body">
 <p>output方式 childText:{{childName}}</p>
 <br>
 <app-output-child (childNameEventEmitter)="showChildName($event)"></app-output-child>
</p>
 child.component.ts
 export class OutputChildComponent implements OnInit {
 // 传入的回调事件
 @Output() public childNameEventEmitter: EventEmitter<any> = new EventEmitter();
 constructor() { }
 ngOnInit() {
 }
 showMyName(value) {
 //这里就执行,父组件传入的函数
 this.childNameEventEmitter.emit(value);
 }
}

注入父组件

这个原理的原因是父,子组件本质生命周期是一样的

export class OutputChildComponent implements OnInit {
 // 注入父组件
 constructor(private childToParentComponent: ChildToParentComponent) { }
 ngOnInit() {
 }
 showMyName(value) {
 this.childToParentComponent.childNameForInject = value;
 }
}

sibling组件 => sibling组件

service

Rxjs

通过service通信

angular中service是单例的,所以三种通信类型都可以通过service,很多前端对单例理解的不是很清楚,本质就是
,你在某个module中注入service,所有这个modul的component都可以拿到这个service的属性,方法,是共享的,所以常在app.moudule.ts注入日志service,http拦截service,在子module注入的service,只能这个子module能共享,在component注入的service,就只能子的component的能拿到service,下面以注入到app.module.ts,的service来演示

user.service.ts
@Injectable()
export class UserService {
 age: number;
 userName: string;
 constructor() { }
}
app.module.ts
@NgModule({
 declarations: [
 AppComponent,
 SiblingAComponent,
 SiblingBComponent
 ],
 imports: [
 BrowserModule
 ],
 providers: [UserService],
 bootstrap: [AppComponent]
})
export class AppModule { }
SiblingBComponent.ts
@Component({
 selector: 'app-sibling-b',
 templateUrl: './sibling-b.component.html',
 styleUrls: ['./sibling-b.component.css']
})
export class SiblingBComponent implements OnInit {
 constructor(private userService: UserService) {
 this.userService.userName = "王二";
 }
 ngOnInit() {
 }
}
SiblingAComponent.ts
@Component({
 selector: 'app-sibling-a',
 templateUrl: './sibling-a.component.html',
 styleUrls: ['./sibling-a.component.css']
})
export class SiblingAComponent implements OnInit {
 userName: string;
 constructor(private userService: UserService) {
 }
 ngOnInit() {
 this.userName = this.userService.userName;
 }
}

通过Rx.js通信

这个是最牛逼的,基于订阅发布的这种流文件处理,一旦订阅,发布的源头发生改变,订阅者就能拿到这个变化;这样说不是很好理解,简单解释就是,b.js,c.js,d.js订阅了a.js里某个值变化,b.js,c.js,d.js立马获取到这个变化的,但是a.js并没有主动调用b.js,c.js,d.js这些里面的方法,举个简单的例子,每个页面在处理ajax请求的时候,都有一弹出的提示信息,一般我会在
组件的template中中放一个提示框的组件,这样很繁琐每个组件都要来一次,如果基于Rx.js,就可以在app.component.ts中放这个提示组件,然后app.component.ts订阅公共的service,就比较省事了,代码如下
首先搞一个alset.service.ts

import {Injectable} from "@angular/core";
import {Subject} from "rxjs/Subject";
@Injectable()
export class AlertService {
 private messageSu = new Subject<string>(); //
 messageObserve = this.messageSu.asObservable();
 private setMessage(message: string) {
 this.messageSu.next(message);
 }
 public success(message: string, callback?: Function) {
 this.setMessage(message);
 callback();
 }
}

sibling-a.component.ts

@Component({
 selector: 'app-sibling-a',
 templateUrl: './sibling-a.component.html',
 styleUrls: ['./sibling-a.component.css']
})
export class SiblingAComponent implements OnInit {
 userName: string;
 constructor(private userService: UserService, private alertService: AlertService) {
 }
 ngOnInit() {
 this.userName = this.userService.userName;
 // 改变alertService的信息源
 this.alertService.success("初始化成功");
 }
}

app.component.ts

@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 title = 'app';
 message: string;
 constructor(private alertService: AlertService) {
 //订阅alertServcie的message服务
 this.alertService.messageObserve.subscribe((res: any) => {
 this.message = res;
 });
 }
}

这样订阅者就能动态的跟着发布源变化

总结:

下载本文
显示全文
专题