在实际的应用中我们的组件将会以树形的结构进行关联,所以组件间的关系主要就是:
父子关系
兄弟关系
无直接关系
【相关教程推荐:《angular教程》】准备一下我们的环境:
1、创建一个header组件: ng g c components/header
<app-button></app-button><app-title></app-title><app-button></app-button>
export class headercomponent implements oninit { constructor() {} ngoninit(): void {}}
2、创建一个title组件: ng g c components/title
<span>{{title}}</span>
export class titlecomponent implements oninit { public title: string = '标题'; constructor() {} ngoninit(): void {}}
3、创建一个button组件: ng g c components/button
<button>{{ btnname }}</button>
export class buttoncomponent implements oninit { public btnname: string = '按钮'; constructor() {} ngoninit(): void {}}
直接调用
适用于父子关系组件,注意点是直接调用使得父子组件的耦合性变高,要明确使用确实需要直接调用。
1、将我们的header组件挂载到app中,使得app和header之间形成父子组件关系
2、使用#为我们的组件起一个名称: <app-header #header></app-header>
3、现在我们的header组件还很空,我们扩展一下,要不然调用什么呢?
export class headercomponent implements oninit { public name: string = 'headercomponent'; printname(): void { console.log('component name is', this.name); }}
4、组件扩展好以后我们就可以在父组件app中调用子组件header中的属性和函数了
<app-header #header></app-header><p> 调用子组件属性: {{ header.name }} <button (click)="header.printname()">调用子组件函数</button></p>
5、第4步是在父组件的html模板中进行操作,有时候我们还需要在父组件的ts类中对子组件进行操作,我们接下来接着演示。
6、我们需要用到一个新的装饰器@viewchild(component)
export class appcomponent { title = 'angular-course'; @viewchild(headercomponent) private header!: headercomponent; // 声明周期钩子: 组件及子组件视图更新后调用,执行一次 ngafterviewinit(): void { // 调用子组件属性 console.log(this.header.name); // 调用子组件函数 this.header.printname(); }}
@input和@output
适用于父子关系组件
1、我们通过在header组件中定义title,来解耦title组件中直接调用导致扩展复杂的问题
2、为title组件中的title属性增加@input()装饰器: @input() public title: string = '标题';
3、为header组件新增title属性并赋值: public title: string = '我是新标题';
4、我们再header组件的html模板中这样来使用title组件: <app-title [title]="title"></app-title>
5、一起看看到现在的效果吧,界面虽然丑,但是下次使用组件时title设置是不是方便一点呢?
6、以上步骤实现了父组件的数据传递到了子组件中,那么我们接着来看子组件的数据怎么传递到父组件中呢? 我们一起来用@output()装饰器实现以下吧
7、在title组件的ts类中增加titlechange属性: @output() public titlechange = new eventemitter();
8、在title组件的ts类中定时派发数据
ngoninit(): void { // 定时将子组件的数据进行派发 setinterval(() => { this.titlechange.emit(this.title); }, 1500);}
9、现在我们来修改header父组件来接收派发来的数据:
<app-title [title]="title" (titlechange)="onchildtitlechange($event)"></app-title>
onchildtitlechange(value: any) { console.log('onchildtitlechange: >>', value);}
利用服务单利进行通信
适用于无直接关系组件
1、既然要通过服务来做通信,那我们就先创建一个服务吧: ng g s services/eventbus,并且我们声明了一个类型为subject的属性来辅助通信
@injectable({ providedin: 'root',})export class eventbusservice { public eventbus: subject<any> = new subject(); constructor() {}}
2、我们为了省事就不重新创建组件了,因为我们的header中的按钮组件和title组件就符合没有直接关系的组件。
3、改造一下我们的button组件,并且添加点击事件来触发triggereventbus函数
export class buttoncomponent implements oninit { public btnname: string = '按钮'; constructor(public eventbusservice: eventbusservice) {} ngoninit(): void {} public triggereventbus(): void { this.eventbusservice.eventbus.next('我是按钮组件'); }}
4、在title组件中模拟数据的获取
export class titlecomponent implements oninit { constructor(public eventbusservice: eventbusservice) {} ngoninit(): void { this.eventbusservice.eventbus.subscribe((value) => { console.log(value); }); }}
利用cookie、session或者localstorage进行通信
1、这个就很简单了,我们还是用title组件和button组件来做演示,这次我们在title组件中将数据保存,在button组件中获取数据。我们仅演示localstorage吧,其他都雷同的。
2、在title组件的ngoninit()钩子中保存title到localstorage中: window.localstorage.setitem('title', this.title);
3、在button组件中获取数据: const title = window.localstorage.getitem('title');
结语:
本篇我们介绍了angular的组件通信,为我们拆分后的组件可以进行合理的通信提供了保障,我们到现在组件的使用都是通过引入标签的方式进行。
原文地址:https://juejin.cn/post/6991471300837572638
作者:小鑫同学
更多编程相关知识,请访问:编程入门!!
以上就是angular组件怎么进行通信?父子组件通信的2种方法的详细内容。