问题: 一个组件什么时候放在另一个组件内?
比如我有一个 Content
组件,它有2个子组件 List
和 Player
。点击一个 List
元素将加载一个视频到 Player
中。那么问题来了,是否 Player
组件是否应当放在 List
组件当中,他们之间是如何进行交互的?
答案
有一个被大家都接受的架构模式称之为 智能组件和呈现组件(smart component && dumb component).
简而言之,就本问题来讲, ContentComponent
组件将是一个智能组件,它将状态和属性传递给它的子组件,即将 videos
传递给 ListComponent
, 将 chosenVideo
(选中的那个视频)传递给 PlayerComponent
组件。我们可以在 ListComponent
组件中通过自定义事件(emit an Event) 来更新 PlayComponent
中播放的视频
下面代码示例:
// ContentComponent 父组件
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
@Component({
selector: 'my-content',
template: `
<my-list [list]="list | async" (onChosenVideo)="setVideo($event)"></my-list>
<my-player [video]="chosenVideo"></my-player>
`
})
export class ContentComponent implements OnInit {
// 这个组件用于接收外界状态,即从某个视频服务哪里获取所有的videos
list: Observable<Video[]>;
// 这个属性表示被选中的那个视频
chosenVideo: Video;
constructor(
private videoService: SomeVideoService // 注入该视频服务
) {}
ngOnInit() {
// 获取video lists
this.list = this.videoService.getVideosFromSomeAPISomewhere();
}
// 父组件的方法 设置选中的组件
setVideo(video: Video) {
this.chosenVideo = video;
}
}
// 子组件
// ListComponent
@Component({
selector: 'my-list',
template: `
<ul *ngFor="let video of videos">
<li (click)="setVideo(video)"> {{ video.title}}</li>
</ul>
`
})
export class ListComponent {
// ListComponent 不关心视频数组从哪里来,它只获取数据即可,即将属性从别处输入到这个组件(Input)
// 这可以认为是组件API的一部分
// 当别人要使用ListComponent组件时,他的责任就是坚持上面的原则
@Input list: Video[];
// 当使用ListComponent组件时, ListComponent向外输出一个事件,
// 这也是ListComponent组件API的一部分
// 相当于自定义事件, 和父组件进行交互
@Output() onChoseVideo: EventEmitter = new EventEmitter();
setVideo(video: Video) {
this.onChoseVideo.emit(video); // 向外传递这个这个值
}
}
// PlayerComponent
@Component({
selector: 'my-player',
template: `
<div id="player"><!-- your video player html element here --></div>
`
})
export class PlayerComponent {
// 这个组件只关心输入进来的Video,它不关心视频从哪里来
@Input video: Video;
}
export class Video {
title: string;
id: string;
description: string
}
这篇文章来自 reddit angular2 讨论区, 这对父子组件之间的交互讲解的十分的透彻,值得反复的看。
相关文章:
另外这篇文章讲解得很清楚:
网友评论