如何在Angular中配置课程课时播放器,实现点击课时加载对应视频
实现思路
你当前的两个组件属于同父级的兄弟组件,轻量场景下通过父组件做状态中转即可实现通信,整体链路为「课时组件抛出选中事件→父组件接收并存储当前选中课时→父组件将选中课时传递给播放器」,实现成本低且易维护。
第一步:改造课时列表组件(app-lesson-card)
给课时项增加点击事件,通过Output将选中的课时抛给父组件:
- 组件类新增Output事件和点击处理逻辑:
import { Component, Input, Output, EventEmitter } from '@angular/core'; export class LessonCardComponent { @Input() course: ICourse; // 对外抛出选中的课时 @Output() lessonSelected = new EventEmitter<ILesson>(); onLessonClick(lesson: ILesson) { // 已报名才允许切换课时,未报名可自行扩展提示逻辑 if (this.course.enrolled) { this.lessonSelected.emit(lesson); } } // 保留你原有的enrollCourse等逻辑 }
- 模板中给课时行绑定点击事件:
<!-- 原有循环行新增点击事件和样式提示 --> <div class='flex items-center justify-between top-margin' *ngFor='let lessonData of course.lessons' (click)="onLessonClick(lessonData)" [ngClass]="{'cursor-pointer': course.enrolled, 'opacity-70': !course.enrolled}"> <!-- 内部原有内容保持不变 --> </div>
第二步:改造父组件做状态中转
- 父组件类新增当前选中课时的存储逻辑:
export class CourseDetailsComponent { course: ICourse; // 你原有定义的课程属性 currentLesson: ILesson; // 存储当前选中的课时 // 你原有获取课程数据的逻辑里,加默认播放第一个课时的赋值 fetchCourseInfo() { // 原有接口请求逻辑 this.course = 接口返回的课程数据; this.currentLesson = this.course.lessons[0]; } // 接收课时组件抛出的选中事件 onLessonSelected(lesson: ILesson) { this.currentLesson = lesson; } }
- 父组件模板绑定事件和传值:
<div class='course-details'> <div> <!-- 给播放器新增传递当前选中课时 --> <app-course-player [course]='course' [currentLesson]="currentLesson"></app-course-player> </div> <div> <!-- 监听课时组件的选中事件 --> <app-lesson-card class='w-full' [course]='course' (lessonSelected)="onLessonSelected($event)"></app-lesson-card> </div> </div>
第三步:改造播放器组件适配切换逻辑
你原有代码用*ngFor循环了所有课时的播放器,会渲染多个播放器实例,需要调整为只渲染当前选中的课时:
- 播放器组件类新增Input属性:
import { Component, Input, ViewChild, ElementRef, SimpleChanges } from '@angular/core'; export class CoursePlayerComponent { @Input() course: ICourse; @Input() currentLesson: ILesson; @ViewChild('myMedia') myMedia: ElementRef<HTMLVideoElement>; // 用于操作播放器 // 可选:切换课时后自动播放 ngOnChanges(changes: SimpleChanges) { if (changes['currentLesson'] && this.myMedia) { this.myMedia.nativeElement.play(); } } }
- 播放器模板去掉循环,直接使用当前选中课时:
<!-- 去掉原来的*ngFor循环外层div --> <vg-player class='w-full video-size'> <vg-overlay-play vgFor='dreamclass-video'></vg-overlay-play> <vg-controls> <vg-play-pause></vg-play-pause> <vg-playback-button></vg-playback-button> <vg-scrub-bar> <vg-scrub-bar-current-time></vg-scrub-bar-current-time> <vg-scrub-bar-buffering-time></vg-scrub-bar-buffering-time> </vg-scrub-bar> <vg-time-display vgProperty='left' vgFormat='mm:ss'></vg-time-display> <vg-mute></vg-mute> <vg-fullscreen></vg-fullscreen> </vg-controls> <video #myMedia [vgMedia]='myMedia' [poster]='"img-proxy/plain/" + currentLesson.coverUrl' id='dreamclass-video' [src]='currentLesson.videoUrl'> </video> </vg-player>
其他可选方案
如果你的项目层级较深、选中课时状态需要跨多组件复用,可以单独封装一个课程状态服务,通过BehaviorSubject存储当前选中课时,两个子组件都注入服务实现通信,适合复杂业务场景。
内容的提问来源于stack exchange,提问作者digitalboot
相关产品推荐
相关产品推荐

