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 实现完整版本~

相关推荐
天外来鹿2 小时前
Map/Set/WeakMap/WeakSet学习笔记
前端·javascript·笔记·学习
Luna-player2 小时前
前端中stylus是干嘛用的
前端·css·stylus
新科技事物2 小时前
AI编曲软件帮原创音乐人,用清唱歌词的音频快速做出专业的歌曲编曲伴奏
人工智能·音视频
CHQIUU2 小时前
解决 npm 全局安装 EACCES 权限问题(macOS 篇)
前端·macos·npm
程序员鱼皮2 小时前
OpenClaw接入飞书保姆级教程,几分钟搞定手机养龙虾!
前端·人工智能·后端
紫_龙2 小时前
最新版vue3+TypeScript开发入门到实战教程之vue3与vue2语法优劣对比
前端·javascript·typescript
新科技事物2 小时前
AI编曲软件提升出歌效率,原创音乐人凭清唱歌词的音频快速作编曲伴奏成歌
人工智能·音视频
SouthRosefinch3 小时前
一、HTML简介与开发环境
开发语言·前端·html
全栈小53 小时前
【前端】Vue 组件开发中的枚举值验证:从一个Type属性错误说起
前端·javascript·vue.js