如何使用 Vue3 和 element-plus 实现图片上传组件
前言
element-plus 提供了 uploader 组件,但是不好定制化,所以自己又造了个轮子,实现了一个图片上传的组件,它的预期行为是:
- 还没上传图片时,显示上传卡片
- 上传图片时显示进度条,隐藏上传卡片
- 上传成功时显示图片缩略图,上传失败则显示失败提示
- 支持上传图片的预览和删除
具体如下图所示:
具体代码
图片上传
这里使用的图床是牛图网,无需注册,貌似也没有图片大小的限制,但是请不要上传违规图像。
import axios from "axios"
import { ElMessage } from 'element-plus'
const service = axios.create({
baseURL: "/image"
})
service.interceptors.response.use(response => {
const code = response.data.code || 200
if (code === 200) {
return response.data.data
}
let msg = response.data.code + " " + response.data.msg
ElMessage.error(msg)
return Promise.reject('上传图片失败:' + msg)
})
/**
* 上传图片
* @param {File} file 图片文件
* @param {RefImpl} progress 上传进度
* @returns promise
*/
function uploadImage(file, progress) {
let formData = new FormData();
formData.append("file", file)
return service({
url: "/upload",
method: "post",
data: formData,
onUploadProgress(event) {
let v = Math.round(event.loaded / event.total * 100)
progress.value = v == 100 ? 80 : v
},
})
}
export { uploadImage }
这里使用 onUploadProgress 来监视上传进度,但是实际上直接使用计算出来的进度往往会和实际的存在很大的偏差,也就是说:即使你还在上传,axios 也会告诉你已经上传完了,所以这里把 100 的进度换成了 80,真正的 100 进度应该在服务器返回 url 时设置。
受到同源策略的限制,我们需要在 vue.config.js 中配置一下代理服务器:
module.exports = {
devServer: {
proxy: {
"/image": {
target: "https://niupic.com/api",
pathRewrite: { "^/image": "" },
},
}
}
}
上传组件
图片预览功能用的是 vue-easy-light-box,如果没有安装的话可以 npm install --save vue-easy-lightbox@next 安装一下。下面是具体代码:
在图片上传之前、上传完成和移除图片的时候都会触发相应的自定义事件,父级组件可以处理这些事件来设置图片 url。以上~