vue3从本地选择一个视频 展示到视频组件中

选择视频 例子测试没有通过,需要根据官方文档重新写

基于 Vue3 + Vite + UI 库开发 WebApp(H5 应用)

另外调用相机拍照 和录音需要测试

html 复制代码
<template>
  <div class="video-upload-container" style="padding: 20px; max-width: 500px; margin: 0 auto;">
    <!-- 1. 美化后的文件选择按钮 -->
    <label class="custom-file-btn">
      选择本地视频
      <input
        type="file"
        accept="video/*"
        @change="handleVideoSelect"
        class="file-input"
      />
    </label>

    <!-- 2. 固定宽高的视频预览组件 -->
    <div class="video-preview-wrapper" v-if="videoUrl">
      <video
        :src="videoUrl"
        controls
        class="video-player"
        poster=""
      >
        您的浏览器不支持视频播放
      </video>
    </div>

    <!-- 3. 无视频时的占位提示 -->
    <div v-else class="video-placeholder">
      请选择本地视频文件
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onUnmounted } from 'vue'

// 存储视频预览链接
const videoUrl = ref<string>('')

/**
 * 处理视频选择逻辑
 */
const handleVideoSelect = (e: Event) => {
  const target = e.target as HTMLInputElement
  const file = target.files?.[0]

  if (!file) {
    videoUrl.value = ''
    return
  }

  // 校验视频类型
  if (!file.type.startsWith('video/')) {
    alert('请选择有效的视频文件!')
    target.value = ''
    return
  }

  try {
    videoUrl.value = URL.createObjectURL(file)
  } catch (error) {
    console.error('视频预览失败:', error)
    alert('视频预览出错,请重试!')
  }
}

// 组件卸载时释放临时 URL
onUnmounted(() => {
  if (videoUrl.value) {
    URL.revokeObjectURL(videoUrl.value)
  }
})
</script>

<style scoped>
/* 美化文件选择按钮 */
.custom-file-btn {
  display: inline-block;
  padding: 12px 24px;
  background-color: #409eff;
  color: white;
  border-radius: 8px;
  cursor: pointer;
  font-size: 15px;
  transition: background-color 0.3s;
  margin-bottom: 20px;
}

.custom-file-btn:hover {
  background-color: #66b1ff;
}

/* 隐藏原生文件选择框 */
.file-input {
  display: none;
}

/* 视频容器:固定宽高(示例:400x225,16:9比例) */
.video-preview-wrapper {
  width: 400px;
  height: 225px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid #eee;
}

/* 视频组件:填满容器,固定宽高 */
.video-player {
  width: 100%;
  height: 100%;
  object-fit: cover; /* 保持视频比例,填满容器(可选:contain 显示完整视频) */
}

/* 无视频时的占位样式 */
.video-placeholder {
  width: 400px;
  height: 225px;
  line-height: 225px;
  text-align: center;
  color: #999;
  border: 1px dashed #eee;
  border-radius: 8px;
  background-color: #f9f9f9;
}

/* 移动端适配:小屏幕下缩小固定宽高 */
@media (max-width: 420px) {
  .video-preview-wrapper,
  .video-placeholder {
    width: 300px;
    height: 169px; /* 保持16:9比例 */
  }
}
</style>

在 Vue3 项目中,若你遇到「调用系统图库选择图片 / 音频时,却只显示视频」的问题,核心原因并非 Vue3 本身的问题,而是:

  1. 原生 <input type="file">accept 属性在不同系统 / 浏览器下的解析差异;
  2. 移动端系统图库对文件类型的分类逻辑(比如部分安卓机型会把 Live Photo、动图等识别为视频);
  3. 缺少对文件选择行为的精细化控制(仅靠原生 input 无法强制过滤系统图库的展示内容)。

针对这个问题,Vue3 生态中有专门的文件选择 / 媒体选择库可以解决,以下是最实用的方案:

一、核心解决方案:使用成熟的移动端文件选择库

这些库封装了原生文件选择的兼容逻辑,能精准控制图库展示的文件类型,解决「只显示视频」的问题。

表格

库名称 核心优势 安装命令 官网 / 文档地址
Vant Uploader 基于 Vant 生态,适配移动端,支持精准指定文件类型,和你之前用的 Vant 兼容 npm i vant https://vant-contrib.gitee.io/vant/#/zh-CN/uploader
vue3-filepond 功能强大,支持文件类型过滤、预览、裁剪,适配移动端 npm i filepond vue3-filepond https://pqina.nl/filepond/docs/patterns/frameworks/vue/
tdesign-mobile-vue 腾讯出品的移动端组件库,Upload 组件支持精准控制文件类型 npm i tdesign-mobile-vue https://tdesign.tencent.com/mobile-vue/components/upload

二、最推荐:Vant Uploader(和你现有代码兼容)

Vant 是你之前优先选择的 Vue3 移动端库,其 Uploader 组件能精准控制图库展示的文件类型,解决「只显示视频」的问题,且无需额外安装新依赖。

1. 图片选择(强制只显示图片,屏蔽视频)

vue

复制代码
<template>
  <!-- Vant Uploader 图片选择:强制只显示图片 -->
  <van-uploader
    v-model="fileList"
    accept="image/*"
    :before-read="beforeReadImage"
    capture="album"  <!-- 强制打开相册(而非相机) -->
    multiple="false"
    title="选择图片"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { VanUploader } from 'vant'
import 'vant/lib/uploader/style'

const fileList = ref([])

// 前置校验:确保只选图片(兜底过滤)
const beforeReadImage = (file: File) => {
  if (!file.type.startsWith('image/')) {
    alert('请选择图片文件!')
    return false // 阻止上传
  }
  return true
}
</script>
2. 音频选择(强制只显示音频,屏蔽视频 / 图片)

vue

复制代码
<template>
  <van-uploader
    v-model="audioFileList"
    accept="audio/*"
    :before-read="beforeReadAudio"
    capture="album"
    multiple="false"
    title="选择音频"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { VanUploader } from 'vant'
import 'vant/lib/uploader/style'

const audioFileList = ref([])

const beforeReadAudio = (file: File) => {
  if (!file.type.startsWith('audio/')) {
    alert('请选择音频文件!')
    return false
  }
  return true
}
</script>
3. 视频选择(仅显示视频)

vue

复制代码
<template>
  <van-uploader
    v-model="videoFileList"
    accept="video/*"
    :before-read="beforeReadVideo"
    capture="album"
    multiple="false"
    title="选择视频"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { VanUploader } from 'vant'
import 'vant/lib/uploader/style'

const videoFileList = ref([])

const beforeReadVideo = (file: File) => {
  if (!file.type.startsWith('video/')) {
    alert('请选择视频文件!')
    return false
  }
  return true
}
</script>

三、关键配置说明(解决「只显示视频」的核心)

  1. accept 属性精准取值
    • 图片:accept="image/jpeg,image/png,image/gif"(比 image/* 更精准,避免系统误判);
    • 音频:accept="audio/mpeg,audio/wav,audio/flac"
    • 视频:accept="video/mp4,video/avi,video/mov"
  2. capture="album":强制打开系统相册(而非相机),部分机型默认打开相机 + 视频模式,加这个属性可固定打开相册。
  3. before-read 前置校验:即使系统图库过滤失效,也能在代码层兜底过滤,确保只选目标类型文件。

四、为什么原生 input 会出现「只显示视频」?

  1. 系统兼容问题 :安卓部分机型(如小米、华为)对 accept="image/*" 的解析不严格,会把 Live Photo、GIF 动图等识别为视频;
  2. 浏览器差异 :移动端 Safari/Chrome 对 accept 属性的支持度不同,部分浏览器会忽略类型过滤;
  3. 图库分类逻辑:iOS / 安卓的系统图库会按「媒体类型」分类,若默认选中「视频」分类,就会只显示视频(原生 input 无法控制图库的默认分类)。

总结

  1. 解决「图库只显示视频」的核心:放弃原生 input,使用 Vant Uploader 等移动端专用库,其封装了兼容逻辑,能精准控制文件类型;
  2. 关键配置:accept 精准指定文件格式 + capture="album" 强制打开相册 + before-read 前置校验;
  3. 最优选择:优先用 Vant Uploader(和你现有 Vue3 移动端项目兼容,无需额外安装依赖)。

如果需要把图片、视频、音频选择整合为一个组件(带标签切换),可以告诉我,我会帮你基于 Vant Uploader 实现完整版本~

相关推荐
若年封尘5 分钟前
告别手写 API 类型:用 openapi-fetch 打造类型安全的前端接口层
前端·安全·openapi-fetch
cypking11 分钟前
二次封装ElementUI日期范围组件:打造带限制规则的Vue2 v-model响应式通用组件
前端·javascript·elementui
A923A11 分钟前
【小兔鲜电商前台 | 项目笔记】第二天
前端·vue.js·笔记·项目·小兔鲜
牧码岛12 分钟前
Web前端之样式中的light-dark函数,从媒体查询到颜色函数,从颜色到图片,light-dark打开CSS新时代、主题切换的暗黑模式到image的正解
前端·css·web·web前端
酉鬼女又兒25 分钟前
零基础快速入门前端蓝桥杯Web考点深度解析:var、let、const与事件绑定实战(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·javascript·职场和发展·蓝桥杯·es6·html5
宁雨桥36 分钟前
前端项目实现光暗主题切换的完整方案
前端
happymaker062644 分钟前
vue指令扩展以及监视器的使用
前端·javascript·vue.js
还是大剑师兰特44 分钟前
EventBus核心方法用法
javascript·vue.js·大剑师
一只小阿乐1 小时前
vue前端处理流式数据
前端·javascript·ai·大模型·全栈开发·agentai
问道飞鱼1 小时前
【技术方案】面向 Web 系统的《全栈灰度部署方案设计》
前端·全栈·灰度发布