欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

angular 组件通信的几种实现方式

程序员文章站 2022-03-20 15:23:34
单页面应用组件通信有以下几种,这篇文章主要讲 angular 通信 父组件 => 子组件 子组件 => 父组件 组件a = >...

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

angular 组件通信的几种实现方式

  • 父组件 => 子组件
  • 子组件 => 父组件
  • 组件a = > 组件b

父组件 => 子组件 子组件 => 父组件 sibling => sibling
@input @output
setters (本质上还是@input) 注入父组件
ngonchanges() (不推荐使用)
局部变量
@viewchild()
service service service
rxjs的observalbe rxjs的observalbe rxjs的observalbe
localstorage,sessionstorage localstorage,sessionstorage localstorage,sessionstorage

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

父组件 => 子组件

@input,最常用的一种方式

@component({
 selector: 'app-parent',
template: '<div>childtext:<app-child [textcontent] = "varstring"></app-child></div>',
 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这个变量来表示子组件,就能调用子组件的方法了.

<div 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>
      </div>

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

<div class="panel-body">
 <p>output方式 childtext:{{childname}}</p>
 <br>
 <app-output-child (childnameeventemitter)="showchildname($event)"></app-output-child>
</div>
 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;
  });
 }
}

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

总结: 以上就是常用的的通信方式,各种场景可以采取不同的方法。希望对大家的学习有所帮助,也希望大家多多支持。