思路
- 页面中创建两个
video 标签 - 在组件加载时同时加载两个视频资源(
autoplay),暂时不播放的视频在 canplay 事件中调用暂停方法,使之实现预加载 - 使用绝对定位将预加载的视频移出可视窗口
- 第一个视频结束后,通过
ended 事件播放之前预加载的视频,同时将当前 src 切换为下一个需要播放的视频地址,完成缓存
核心代码
<video ref="video" :class="{'video-hide':!playVideoTag}" autoplay @ended="onEnded('video')"></video>
<video ref="video1" :class="{'video-hide':playVideoTag}" autoplay @ended="onEnded('video1')"></video>
data() {
return {
srcList: [],
curIndex: 0,
playVideoTag: true, // 当前播放的 ref 是否为 video
canPlayNext: true // 是否存在下一个播放地址
}
},
onEnded(e) {
if (this.canPlayNext) {
const video = e === 'video' ? this.$refs.video1 : this.$refs.video
video.play()
this.playVideoTag = !this.playVideoTag
this.loadNext()
}
console.log('onended my video')
this.$emit('ended')
},
playVideo(src) { // 可以接受单个 url 和 url 列表
this.srcList = typeof src === 'string' ? [src] : src
this.$refs.video.src = src[0]
this.srcList = src
this.loadNext()
},
loadNext() {
const video = this.playVideoTag ? this.$refs.video1 : this.$refs.video
if (this.srcList.length - 1 === this.curIndex) { // 当前索引是列表的最后一个
console.log('没有新视频')
this.canPlayNext = false
return
}
video.src = this.srcList[++this.curIndex]
video.addEventListener('canplay', e => e.target.pause(), { once: true })
}
.video-hide{
position: absolute;
top: -10000px;
left: -10000px;
}