Skip to content

UseElUpload - 上传器

组件介绍

UseElUpload 是基于 Element Plus 的 ElUpload 二次封装的文件上传组件,专注于提供开箱即用的文件类型校验、大小限制、数量控制、图片预览、文件下载能力,内置标准化的文件类型配置、删除二次确认、上传中断机制,完整支持 v-model 双向绑定与数据回显,兼容全局上传配置注入,可直接替换原生 ElUpload 使用,大幅降低文件上传场景的重复开发成本。

核心能力

  1. 标准化的文件类型管理

内置四种预设上传类型(ALL/IMG/VIDEO/EXCLUDE_VIDEO),每种类型预配置支持的文件扩展名与用户提示文案,自动生成 accept 属性限制文件选择,上传前自动校验文件后缀合法性,无需手动维护文件类型白名单,IMG 类型自动切换照片墙展示模式。

  1. 开箱即用的上传校验能力

内置文件大小校验(默认最大 2GB,可通过 maxSize 自定义)、文件数量限制(默认单文件,limit 配置数量),超出限制时自动弹出友好提示,上传前拦截非法文件,避免无效请求;limit > 1 时自动开启多文件上传,达到数量上限自动隐藏上传按钮。

  1. 内置图片预览与文件下载

IMG 类型上传的图片点击自动弹出预览弹窗,支持大图查看;非图片类型点击自动触发文件下载,自动从响应数据或回显数据中提取下载链接,无需额外处理预览与下载逻辑,未上传完成的文件自动提示无法预览/下载。

  1. 安全的删除二次确认机制

删除文件前自动弹出二次确认框,避免误删操作;删除正在上传中的文件时,自动通过 AbortController 中断上传请求,释放网络资源,防止无效请求继续占用带宽。

  1. 完善的 v-model 双向绑定

原生支持 fileId 与 linkUrl 的双向绑定,多文件上传时自动将文件 ID 与访问链接用逗号拼接,内部使用 300ms 防抖更新,避免频繁触发响应式更新;上传成功、删除文件、数据回显时自动同步绑定值。

  1. 智能的数据回显能力

通过 uploadList 属性支持已上传文件的数据回显,自动识别文件 ID、原始文件名、访问链接,兼容不同后端返回字段格式;内部标记上传/删除状态,避免用户操作后回显数据覆盖当前文件列表。

  1. 灵活的全局配置支持

支持通过全局配置注入统一的上传地址(action)、请求头(headers)、额外参数(data),组件级 uploadConfig 可覆盖全局配置,遵循「组件局部配置 > 全局默认配置」优先级规则,无需每个组件重复配置上传接口信息。

  1. 拖拽上传与样式统一

默认开启拖拽上传交互,优化上传区域尺寸与样式,修复原生上传组件进度条位置异常、文件名展示不全等样式问题,照片墙模式下去除默认边框保持视觉统一,禁用状态下自动隐藏上传按钮。

  1. 统一的错误处理机制

上传失败时自动解析后端返回错误信息,统一弹出错误提示,通过 onError 事件向外抛出错误详情;上传成功但返回数据格式不符合规范时自动提示,保证错误信息的一致性与可追溯性。

  1. 安全的生命周期管理

组件卸载时自动中断所有正在进行的上传请求,取消防抖函数执行,避免内存泄漏与无效回调;预览弹窗关闭时自动清空预览图片地址,释放资源,保证组件在动态渲染、频繁切换场景下的稳定性。

使用

UseElUpload

Props

ts
import type { PropType } from 'vue'
import type { UploadConfig } from '@/types'

/**
 * 组件props
 */
export default {
  /**
   * 文件id
   */
  fileId: {
    type: String,
    default: ''
  },
  /**
   * 链接地址
   */
  linkUrl: {
    type: String,
    default: ''
  },
  /**
   * 上传配置
   * action:请求URL,eg:'/api/file/upload'
   * headers:设置上传的请求头部,eg:{ Authorization: `Bearer ${token}` }
   * data:上传时附带的额外参数,eg:{ referer: window.location.href }
   */
  uploadConfig: {
    type: Object as PropType<UploadConfig>,
    default: () => ({
      //  action: '/api/file/upload',
      //  headers: { Authorization: `Bearer ${token}` },
      //  data: { referer: window.location.href }
    })
  },
  /**
   * 上传类型
   * 为ALL支持所有文件格式
   * 为IMG仅可上传支持的图片格式且按照片墙形式展示
   * 为VIDEO仅可上传支持的视频格式
   * 为EXCLUDE_VIDEO可上传除视频格式外的所有支持的文件格式
   */
  uploadType: {
    type: String,
    default: 'ALL',
    validator: (value: string) =>
      ['ALL', 'IMG', 'VIDEO', 'EXCLUDE_VIDEO'].includes(value)
  },
  /**
   * 上传提示
   */
  uploadTip: {
    type: String,
    default: ''
  },
  /**
   * 上传列表 用于数据回显
   */
  uploadList: {
    type: Array as PropType<Record<string, unknown>[]>,
    default: () => []
  },
  /**
   * 上传数量限制 默认1
   */
  limit: {
    type: Number,
    default: 1,
    validator: (value: number) => value >= 1
  },
  /**
   * 是否禁用上传 默认否
   */
  disabled: {
    type: Boolean,
    default: false
  },
  /**
   * 最大文件大小 默认2GB
   */
  maxSize: {
    type: Number,
    default: 2
  }
}

Types

ts
import type { ExtractPropTypes } from 'vue'
import componentProps from './props'

/**
 * props类型
 */
export type Props = ExtractPropTypes<typeof componentProps>

/**
 * emits类型
 */
export type Emits = {
  'update:fileId': [value: string | number]
  'update:linkUrl': [url: string]
  onFileObj: [file: Record<string, any>]
  onError: [error: Error | string]
}

基于 MIT 许可发布