使用Vue3实现一个Upload组件

249 阅读2分钟

使用Vue3实现一个Upload组件 通用上传组件开发 开发上传组件前我们需要了解:

FormData上传文件所需API dragOver文件拖拽到区域时触发 dragLeave 文件离开拖动区域 drop文件移动到有效目标时 首先实现一个最基本的上传流程:

基本上传流程,点击按钮选择,完成上传 代码如下:

} })

.page-title { color: #fff; }

复制代码 结果如下:

image.png 到这里我们基本的上传已经处理完成了,相对来说还是比较简单的,接下来我们创建Uploader.vue文件用来封装Upload组件。

我们需要实现如下功能 自定义模版 我们知道使用系统自带样式比较难看所用我们需要如下处理:

对样式进行优化,隐藏input 点击<div class="upload-area" @click="triggerUpload">使用js出发input的click事件 处理上传状态 代码如下:

复制代码 现在我们已经完成了对上传组件样式的优化,和上传状态的处理,接下来我们需要处理文件上传列表

支持文件上传列表 处理文件上传列表我们需要有如下实现:

显示文件名称 状态 可删除 显示上传进度 有可能有更丰富的显示 在上一步代码的基础上做一些修改:

首先我们定义上传文件对象接口类UploadFile 创建了一个filesList响应式对象 去掉了fileStatus,因为在UploadFile接口中我们已经有定义status 修改模版中的状态,利用computed来判读是否是处于上传状态,并增加slot进行自定义 展示上传的图片 处理上传进度 处理删除 注意点:如果选择相同的图片不会进行上传操作,因为我们使用的是input的change事件,所以我们需要在上传后将input的value设置为null

支持一系列生命周期钩子事件,上传事件 beforeUpload

复制代码 实现步骤:

在poops处定义属性beforeUpload,同时定义上传文件为boolean或promsie且接受一个File 将原上传方法进行封装为postFile 根据beforeUpload返回结果,进行接下来的流程处理 onProgress,onSuccess,onError,onChange与之类似

拖拽支持 大致流程如下图:

image.png

dragover和dragleave添加和删除对应的class drop拿到正在被拖拽的文件,删除class,并且触发上传 只有在属性drag为true才能触发 需要注意v-on的使用具体可参考vue官方文档 上代码:

复制代码 以上就是基本的基于vue3实现的上传通用组件 另附上上传接口代码:

// 引入模块 const Koa = require('koa'); const fs = require('fs'); const path = require('path'); const router = require('koa-router')(); const koaBody = require('koa-body'); const static = require('koa-static'); const cors = require('koa2-cors')

// 实例化 const app = new Koa();

app.use(koaBody({ multipart: true, // 支持文件上传 formidable: { maxFieldsSize: 2 * 1024 * 1024, // 最大文件为2兆 multipart: true // 是否支持 multipart-formdate 的表单 } }));

const uploadUrl = "http://localhost:3001/static/upload";

// 配置路由 router.get('/', (ctx) => { // 设置头类型, 如果不设置,会直接下载该页面 ctx.type = 'html'; // 读取文件 const pathUrl = path.join(__dirname, '/static/upload.html'); ctx.body = fs.createReadStream(pathUrl); });

// 上传文件 router.post('/upload', (ctx) => { // 获取上传文件 const file = ctx.request.files.file; console.log(file); // 读取文件流 const fileReader = fs.createReadStream(file.path); // 设置文件保存路径 const filePath = path.join(__dirname, '/static/upload/'); // 组装成绝对路径 const fileResource = filePath + /${file.name};

/**

  • 使用 createWriteStream 写入数据,然后使用管道流pipe拼接 */ const writeStream = fs.createWriteStream(fileResource); // 判断 /static/upload 文件夹是否存在,如果不在的话就创建一个 if (!fs.existsSync(filePath)) { fs.mkdir(filePath, (err) => { if (err) { throw new Error(err); } else { fileReader.pipe(writeStream); ctx.body = { url: uploadUrl + /${file.name}, code: 0, message: '上传成功1' }; } }); } else { fileReader.pipe(writeStream); ctx.body = { url: uploadUrl + /${file.name}, code: 0, message: '上传成功1' }; } });

// 配置静态资源路径 app.use(static(path.join(__dirname))); // 开启跨域 app.use(cors()) // 启动路由 app.use(router.routes()).use(router.allowedMethods());

// 监听端口号 app.listen(3001, () => { console.log('server is listen in 3001'); }); 复制代码 写在最后 已上只是一个简单的实现,当然了我们也可以添加自定义headers,自定义传递数据data,accecpt等等