关注

DOM API - HTMLMediaElement(Video 播放机制与 Vue 实战)

DOM API - HTMLMediaElement(Video 播放机制与 Vue 实战)

一、HTML5 Video 基础

在浏览器中,<video> 元素不只是一个标签,它对应着一个 DOM API 接口对象,让你可以用 JavaScript 去操作视频的播放、暂停、音量、当前时间等行为。

1.1 < video >是什么?

  • HTML5 引入了 <video> 元素
  • 用于在网页里嵌入视频播放器
  • 可以搭配多种属性控制行为(比如 loop、muted、autoplay)

官方文档:视频嵌入元素(MDN 中文)

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> 里:

    1. 执行 setup 代码
    2. 创建虚拟 DOM
    3. 渲染模板
    4. 挂载到真实 DOM
    5. ref 才会有值

还有更优美的写法,Vue 已经帮你封装好了事件系统。

直接在模板里写:

<video
  ref="videoRef"
  @ended="handleEnded"
></video>
const handleEnded = () => {
  console.log('你觉得这个视频怎么样?')
}

转载自CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/weixin_62613321/article/details/158580181

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--