上一篇我们初步了解的Angular中组件及基本的使用,但是所有的功能要是放到一个组件里面必然显得更加冗余,臃肿,我们通常会将组件按照一定的规则进行拆分,拆分后的组件免不了的就需要进行通信,这一篇我们就来一起熟悉一下Angular中的组件通信吧。
在实际的应用中我们的组件将会以树形的结构进行关联,所以组件间的关系主要就是:
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 {}
}
title
组件: ng g c components/title
<span>{{title}}</span>
export class TitleComponent implements OnInit {
public title: string = '标题';
constructor() {}
ngOnInit(): void {}
}
button
组件: ng g c components/button
<button>{{ btnName }}</button>
export class ButtonComponent implements OnInit {
public btnName: string = '按钮';
constructor() {}
ngOnInit(): void {}
}
适用于父子关系组件,注意点是直接调用使得父子组件的耦合性变高,要明确使用确实需要直接调用。
#
为我们的组件起一个名称: <app-header #header></app-header>
export class HeaderComponent implements OnInit {
public name: string = 'HeaderComponent';
printName(): void {
console.log('component name is', this.name);
}
}
<app-header #header></app-header>
<p>
调用子组件属性: {{ header.name }}
<button (click)="header.printName()">调用子组件函数</button>
</p>
@ViewChild(Component)
export class AppComponent {
title = 'angular-course';
@ViewChild(HeaderComponent)
private header!: HeaderComponent;
// 声明周期钩子: 组件及子组件视图更新后调用,执行一次
ngAfterViewInit(): void {
// 调用子组件属性
console.log(this.header.name);
// 调用子组件函数
this.header.printName();
}
}
适用于父子关系组件
header
组件中定义title
,来解耦title
组件中直接调用导致扩展复杂的问题
title
组件中的title
属性增加@Input()装饰器: @Input() public title: string = '标题';
public title: string = '我是新标题';
header
组件的html
模板中这样来使用title
组件: <app-title [title]="title"></app-title>
title
设置是不是方便一点呢?
@Output()
装饰器实现以下吧
title
组件的ts类中增加titleChange
属性: @Output() public titleChange = new EventEmitter();
title
组件的ts类中定时派发数据
ngOnInit(): void {
// 定时将子组件的数据进行派发
setInterval(() => {
this.titleChange.emit(this.title);
}, 1500);
}
<app-title
[title]="title"
(titleChange)="onChildTitleChange($event)">
</app-title>
onChildTitleChange(value: any) {
console.log('onChildTitleChange: >>', value);
}
适用于无直接关系组件
ng g s services/EventBus
,并且我们声明了一个类型为Subject
的属性来辅助通信@Injectable({
providedIn: 'root',
})
export class EventBusService {
public eventBus: Subject<any> = new Subject();
constructor() {}
}
header
中的按钮组件和title组件就符合没有直接关系的组件。
button
组件,并且添加点击事件来触发triggerEventBus
函数
export class ButtonComponent implements OnInit {
public btnName: string = '按钮';
constructor(public eventBusService: EventBusService) {}
ngOnInit(): void {}
public triggerEventBus(): void {
this.eventBusService.eventBus.next('我是按钮组件');
}
}
title
组件中模拟数据的获取export class TitleComponent implements OnInit {
constructor(public eventBusService: EventBusService) {}
ngOnInit(): void {
this.eventBusService.eventBus.subscribe((value) => {
console.log(value);
});
}
}
title
组件和button
组件来做演示,这次我们在title组件中将数据保存,在button
组件中获取数据。我们仅演示localstorage
吧,其他都雷同的。
title
组件的ngOnInit()
钩子中保存title
到localstorage
中: window.localStorage.setItem('title', this.title);
const title = window.localStorage.getItem('title');
本篇我们介绍了Angular的组件通信,为我们拆分后的组件可以进行合理的通信提供了保障,我们到现在组件的使用都是通过引入标签的方式进行,那还有其他的方式来使用我们的组件吗?当然,下一篇我们将一起来熟悉Angular中的动态组件。