优化案例:视频列表只允许单个视频播放
刀刀
7/22/2025
0 字
0 分钟
- 来源:三十的前端课;视频地址:分享一个前端使用设计模式的案例
场景复现
先来看看使用场景,有一个页面会有多个视频组件,现在要求其中一个视频播放时,其他视频都不能播放;上一个正在播放的视频也要停止播放。同时为了减轻包体积,不能使用 pinia
、vuex
这种包管理工具。
项目效果图如下所示:
该项目是一个多人和做项目,组件被拆分为不同开发者负责,所以需要使用到设计模式。
组件代码如下所示:
vue
<script setup>
import HeaderVideo from './components/HeaderVideo.vue'
import VideoList from './components/VideoList.vue'
</script>
<template>
<div>
<HeaderVideo/>
<div>其他内容</div>
<div>其他内容</div>
<VideoList/>
</div>
</template>
vue
<script setup>
import { ref } from 'vue'
import VideoPlayer from './videoPlayer.vue'
</script>
<template>
<div>
<div>我是头部视频组件</div>
<VideoPlayer/>
</div>
</template>
vue
<script setup>
import { ref } from 'vue'
import VideoPlayer from './videoPlayer.vue'
</script>
<template>
<div>
<div>我是视频列表组件</div>
<div>
<VideoPlayer/>
<VideoPlayer/>
<VideoPlayer/>
<VideoPlayer/>
</div>
</div>
</template>
vue
<script setup>
import { ref } from 'vue'
const videoDom = ref(null)
function play() {
videoDom.value.play()
}
function pause() {
videoDom.value.pause()
}
</script>
<template>
<div>
<video ref="videoDom" src="./test.mp4"></video>
<button @click="() => play()">播放</button>
<button @click="() => pause()">暂停</button>
</div>
</template>
运行代码后,现在的效果是点击播放按钮后各自控制各自的视频组件,播放视频。
效果实现
这里用到观察者模式的思想,即一个视频播放时,通知上一个正在播放的视频组件暂停播放。这需要一个变量存储当前播放的视频组件,点击播放按钮时,调用播放函数,传参当前的视频组件 ref
,然后通知上一个正在播放的视频组件暂停播放,再播放当前的视频组件,最后把当前的视频组件 ref
保存起来,用于下一次暂停。
js
export const videoObserver = {
inPlay: null, // 当前正在播放的视频组件ref
playVideo(videoDomRef) {
// 如果有正在播放的视频组件,则暂停播放
if (this.inPlay) {
this.inPlay.pause()
}
videoDomRef.value.play()
this.inPlay = videoDomRef // 保存当前播放的视频组件ref
},
pauseVideo(videoDomRef) {
videoDomRef.value.pause()
}
}
vue
<script setup>
import { ref } from 'vue'
import { videoObserver } from './observer.js'
const videoDom = ref(null)
function play() {
videoDom.value.play()
videoObserver.playVideo(videoDom)
}
function pause() {
videoDom.value.pause()
videoObserver.pauseVideo(videoDom)
}
</script>
<template>
<div>
<video ref="videoDom" src="./test.mp4"></video>
<button @click="() => play()">播放</button>
<button @click="() => pause()">暂停</button>
</div>
</template>
现在开发者无需考虑其他开发者,只需要关注自己的组件即可,这样代码结构清晰,可维护性高。