文章目录
DOM API - HTMLMediaElement(Video 播放机制与 Vue 实战)
一、HTML5 Video 基础
在浏览器中,<video> 元素不只是一个标签,它对应着一个 DOM API 接口对象,让你可以用 JavaScript 去操作视频的播放、暂停、音量、当前时间等行为。
1.1 < video >是什么?
- HTML5 引入了 <video> 元素
- 用于在网页里嵌入视频播放器
- 可以搭配多种属性控制行为(比如 loop、muted、autoplay)
1.2 DOM 对象:HTMLVideoElement
HTMLVideoElement
在 JavaScript 里,DOM 会为每个 <video> 元素创建一个对象,这个对象的类型是:
HTMLVideoElement
//他继承自
HTMLElement → HTMLMediaElement
二、HTMLMediaElement 核心方法
2.1 play()
HTMLVideoElement 的.play()方法
videoRef.value.play()
- 尝试开始播放视频
- 它不是同步函数,而是返回一个 Promise。
为什么返回 Promise?
从浏览器策略上讲,自动播放可能被阻止或者需要用户交互(比如点击/悬停)才能播放。
因此:
- 如果播放成功,Promise resolve
- 如果失败,就返回 rejected promise(比如浏览器不允许播放)
为什么要用 .catch()?
因为没有写 .catch() 的话,如果播放失败就会出现:
Uncaught (in promise) DOMException
所以通常写成:
videoRef.value.play().catch(() => {
// 忽略播放失败
})
2.2 pause()
HTMLVideoElement 的.pause()方法
除了播放,视频还有暂停功能:
videoRef.value.pause()
它的作用是:
暂停当前视频播放
返回值是 undefined(不像 play 返回 Promise)。
三、常见属性与控制能力
常见的视频属性
| 属性 | 作用 |
|---|---|
| muted | 静音播放 |
| loop | 循环播放 |
| src | 视频地址 |
| currentTime | 当前播放时间(秒) |
| play() | 开始播放 |
| pause() | 暂停播放 |
举例来说:
<video muted loop playsinline></video>
- muted → 静音(自动播放通常需要静音才允许)
- loop → 播放结束后自动从头开始
- playsinline → 移动端不强制全屏播放
四、媒体事件系统
<video> 不仅有方法,还会触发事件,例如:
- play → 视频开始播放
- pause → 视频暂停
- loadeddata → 视频第一帧已经加载
- ended → 视频播放结束
可以使用如下代码,监听事件:
videoRef.value.addEventListener('play', () => {...})
五、一个具体实例
<div class="showcase-card" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
<!-- 背景媒体层(图片或视频) -->
<div class="showcase-card-bg">
<video
v-if="backgroundVideo"
ref="videoRef"
:src="backgroundVideo"
class="showcase-card-bg-video"
loop
muted
playsinline
/>
<img v-else :src="backgroundImage" :alt="alt" class="showcase-card-bg-image" />
</div>
// 视频元素引用
const videoRef = ref<HTMLVideoElement | null>(null)
// 鼠标悬停时播放视频
const handleMouseEnter = () => {
if (videoRef.value) {
videoRef.value.play().catch(() => {
// 忽略播放错误(可能是浏览器策略限制)
})
}
}
// 鼠标离开时暂停视频
const handleMouseLeave = () => {
if (videoRef.value) {
videoRef.value.pause()
}
}
解释说明:
@mouseenter=“handleMouseEnter” @mouseleave=“handleMouseLeave” 表示鼠标的移入移出
其中的
const handleMouseEnter = () => {
if (videoRef.value) {
videoRef.value.play().catch(() => {
// 忽略播放错误(可能是浏览器策略限制)
})
}
}
更直观写法
if (videoRef.value) {
const promise = videoRef.value.play()
promise.catch((error) => {
console.log('播放失败', error)
})
}
- 必须使用 catch 或 try/catch 处理
- 否则会出现 Uncaught (in promise) 错误
六、实战小demo
功能需求:
1.鼠标悬浮->播放视频
2.鼠标移出->暂停并重置
3.视频播放结束之后->触发自定义事件->控制台打印:你觉得这个视频怎么样?

父组件 App.vue
<script setup lang="ts">
import VideoTest from './views/VideoTest/index.vue'
</script>
<template>
<div class="container" >
<VideoTest />
</div>
</template>
<style scoped>
.container{
width: 500px;
height: 500px;
}
</style>
子组件
<script setup lang="ts">
import { ref } from 'vue';
import { onMounted } from 'vue';
const videoRef = ref<HTMLVideoElement | null>(null);
const handleMouseenter = () => {
const playPromise = videoRef.value?.play();
playPromise.catch((error) => {
console.log(error);
});
console.log('mouseenter');
}
const handleMouseleave = () => {
if (videoRef.value) {
videoRef.value.pause();
// 重置视频进度
videoRef.value.currentTime = 0;
}
}
onMounted(() => {
videoRef.value?.addEventListener('ended', () => {
console.log('你觉得这个视频怎么样?');
});
});
</script>
<template>
<div class="video-container" @mouseenter="handleMouseenter" @mouseleave="handleMouseleave">
<video src="@/assets/video/2-1.mp4" class="video" ref="videoRef"></video>
</div>
</template>
<style scoped>
.video {
width: 100%;
height: 100%;
}
</style>
-
注意videoRef.value?.addEventListener 这部分放在挂载阶段
在 <script setup> 里:
- 执行 setup 代码
- 创建虚拟 DOM
- 渲染模板
- 挂载到真实 DOM
- ref 才会有值
还有更优美的写法,Vue 已经帮你封装好了事件系统。
直接在模板里写:
<video
ref="videoRef"
@ended="handleEnded"
></video>
const handleEnded = () => {
console.log('你觉得这个视频怎么样?')
}
转载自CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/weixin_62613321/article/details/158580181



