Vue3 + ElementPlus实战:手把手教你实现带预览功能的el-upload文件上传(附完整代码)

Vue3 + Element Plus 文件上传实战:从零构建带预览与手动提交的企业级上传组件

最近在重构一个后台管理系统,文件上传功能几乎是每个项目都绕不开的环节。Element Plus 的 el-upload 组件虽然功能强大,但实际项目中总会遇到各种定制化需求:手动触发上传、图片预览、文件类型限制、大小校验,还有那个让人头疼的 Content-Type 问题。今天我就结合最近的项目实践,分享一套完整的解决方案。

很多开发者习惯直接用 action 属性配置后端接口,这种方式简单但不够灵活。当我们需要在用户选择文件后先进行本地校验,或者需要等待用户填写完表单再统一提交时,手动上传模式就显得尤为重要。而且,图片预览功能在管理系统中几乎是标配,用户需要在上传前就能看到图片内容,避免传错文件。

1. 环境搭建与基础配置

1.1 项目初始化与依赖安装

首先确保你已经有一个 Vue3 项目,如果还没有,可以使用 Vite 快速创建一个:

npm create vue@latest my-upload-project
cd my-upload-project
npm install

接下来安装 Element Plus 及其图标库:

npm install element-plus @element-plus/icons-vue

main.jsmain.ts 中引入 Element Plus:

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

提示:如果你使用 TypeScript,建议同时安装 @types/node 以获得更好的类型支持。

1.2 理解 el-upload 的核心属性

在开始编码前,我们先梳理一下 el-upload 的几个关键属性,这些属性决定了组件的行为模式:

属性 类型 默认值 说明
action string - 上传的地址,手动上传时可设为 "#"
auto-upload boolean true 是否在选择文件后立即自动上传
http-request function - 自定义上传的实现,覆盖默认行为
file-list array [] 已上传的文件列表,支持双向绑定
on-change function - 文件状态改变时的回调
before-upload function - 上传文件前的钩子,可进行校验
list-type string 'text' 文件列表的展示类型
limit number - 允许上传文件的最大数量

这里有个常见的误区:很多人以为 before-upload 钩子在手动上传模式下不会触发。实际上,无论是否自动上传,before-upload 都会在执行上传操作时触发。区别在于,自动上传时选择文件后立即触发,手动上传时则在调用 submit() 方法时触发。

2. 手动上传模式的核心实现

2.1 基础组件结构搭建

我们先创建一个基础的图片上传组件,支持手动触发上传:

<template>
  <div class="upload-container">
    <el-upload
      ref="uploadRef"
      action="#"
      :file-list="fileList"
      :auto-upload="false"
      :multiple="true"
      :limit="9"
      accept="image/*"
      list-type="picture-card"
      :on-change="handleFileChange"
      :on-remove="handleRemove"
      :before-upload="beforeUpload"
    >
      <el-icon><Plus /></el-icon>
      <template #tip>
        <div class="el-upload__tip">
          支持上传 JPG、PNG 格式图片,单张不超过 2MB
        </div>
      </template>
    </el-upload>
    
    <div class="action-buttons">
      <el-button type="primary" @click="handleSubmit" :loading="uploading">
        确认上传
      </el-button>
      <el-button @click="handleClear">清空列表</el-button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

const uploadRef = ref()
const fileList = ref([])
const uploading = ref(false)
const rawFiles = ref([]) // 存储原始文件对象
</script>

这个基础结构有几个关键点:

  • action="#" 表示我们不使用默认的上传行为
  • :auto-upload="false" 关闭自动上传
  • list-type="picture-card" 使用卡片式布局,适合图片展示
  • 通过 ref 获取组件实例,后续可以调用其 submit() 方法

2.2 文件状态管理与校验逻辑

文件校验是上传功能中至关重要的一环。我们需要在用户选择文件时进行即时校验,避免无效文件进入上传队列:

const handleFileChange = (file, files) => {
  // file 是当前变化的文件,files 是当前所有文件
  console.log('文件变化:', file.name, file.status)
  
  // 存储原始文件对象,用于后续 FormData 构建
  if (file.raw) {
    const existingIndex = rawFiles.value.findIndex(f => f.uid === file.uid)
    if (existingIndex === -1) {
      rawFiles.value.push(file.raw)
    }
  }
  
  // 实时更新文件列表
  fileList.value = files
}

const beforeUpload = (file) => {
  // 文件类型校验
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
  if (!allowedTypes.includes(file.type)) {
    ElMessage.error('只支持 JPG、PNG、GIF、WebP 格式的图片')
    return false
  }
  
  // 文件大小校验(2MB)
  const maxSize = 2 * 1024 * 1024
  if (file.size > maxSize) {
    ElMessage.error('图片大小不能超过 2MB')
    return false
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值