Ant-Design-Vue 图片上传
功能演示
我们要实现的功能如下,有两个按钮,点击第一个按钮选择文件,选择文件后点击第二个按钮上传到服务器。
功能需求:
-
只允许上传
png
、jpg/jpeg
格式的图片 -
没有上传图片时显示占位图
-
选择完图片后在页面中渲染出来
构建页面
template
<template>
<div>
<div>
<!-- 选择图片后展示待上传的图片 -->
<img v-if="base64img" :src="base64img" />
<!-- ↓ 没有选择时显示占位图 -->
<img v-else="base64img" src="@/assets/placeholderImg.png" />
</div>
<!-- 限制最大待上传的文件数量为 1 -->
<!-- 添加选择文件后的回调和移除待上传文件的回调 -->
<a-upload :before-upload="beforeUpload" :max-count="1" @remove="handleRemove">
<a-button>
<upload-outlined></upload-outlined>
Select File
</a-button>
</a-upload>
<!-- 点击上传按钮 -->
<a-button @click="triggerUpload" :loading="btnLoading">上传</a-button>
</div>
逻辑部分
TypeScript
import { UploadOutlined } from '@ant-design/icons-vue'
import fruitApi from "@/api/fruitApi";
import {ref} from "vue";
import {Upload} from "ant-design-vue";
import {Notice} from "@/utils/interfaces";
const fileList = ref();
// ↑ 待上传文件列表 (其实里面也就能放一个文件)
const base64img = ref();
// ↑ 我们在页面中显示待上传的图片的原理是
// 将所选择的本地图片转换为 Base64 编码
// 之后让图片的 src = base64img 来实现的
// 所以 base64img 就是一个储存图片编码的字符串
const btnLoading = ref<boolean>(false);
// ↑ 上传按钮的 loading 状态
// 在点击上传 至 获取服务器回调的时间内 按钮不可用
/**
* 对图片编码的函数
*/
function getBase64(img: Blob, callback: (base64Url: string) => void) {
const reader = new FileReader();
reader.addEventListener('load', () => callback(<string>reader.result));
// ↑ 监听 reader 的 load 事件,触发时执行回调函数
// 回调函数的作用就是将图片编码的base64字符串传给 base64img
reader.readAsDataURL(img);
}
/**
* andv 上传文件的回调
* 返回 false 则不会上传文件,而是由我们手动上传
* 返回 Upload.LIST_IGNORE 会取消将文件添加至待上传列表
* @param file 所选择的文件
*/
function beforeUpload(file: any) {
console.log(file);
// 判断文件是否为图片格式
const isImg = (file.type === 'image/jpeg' || file.type === 'image/png');
// 如果文件不是图片格式则禁止上传
if (!isImg) {
Notice.error("只能上传 jpeg/jpg/png 格式的文件!");
// ↑ Notice.error 是我自己写的 Notice 类的一个静态函数
// 用的是 antdv 的 Notifiacation
return Upload.LIST_IGNORE;
}
fileList.value = file;
// ↓ 获取所需要上传图片的 Base64 编码
getBase64(fileList.value, (cb_img: string) => {
// 将获取到的所要上传图片的 Base64 编码渲染到图片上
base64img.value = cb_img;
})
return false;
}
/**
* 点击上传按钮的回调
*/
function triggerUpload() {
const formData = new FormData();
// 对文件列表 判空
if (fileList.value != null) {
formData.append("file", fileList.value as any);
} else {
Notice.error("文件不能为空!")
return Upload.LIST_IGNORE;
}
// ↓ 在上传过程中,按钮为 loading 状态
btnLoading.value = true;
// 请求上传接口
fruitApi({
method: 'put',
url: 'api/upload',
data: formData
})
.then((resp: any) => {
console.log(resp);
if (resp.code === 1) {
Notice.success(<string>resp.data);
changeUploadItemColor("#49aa19");
} else {
Notice.error("上传失败~");
changeUploadItemColor("#ff4d4f");
// ↑ 下面会提到这个函数
}
btnLoading.value = false;
})
.catch((err) => {
console.log(err);
Notice.error("发生了错误~");
btnLoading.value = false;
changeUploadItemColor("#ff4d4f");
})
}
/**
* 待上传图片被删除的回调
*/
function handleRemove() {
fileList.value = null;
// ↑ 置空待上传文件列表
base64img.value = null;
// ↑ 显示默认占位图
}
/**
* 上传图片成功或失败后 list 变色的函数
*/
type uploadItemColor = "#49aa19" | "#ff4d4f";
// ↑ 两个颜色 绿 和 红
function changeUploadItemColor(color: uploadItemColor) {
const uploadListItem = document.querySelector(".ant-upload-list-item-name");
// ↑ 类名是 antdv 规定的,选择这个类名即可
(uploadListItem as any).style.color = color;
// ↑ 使item文字变色
}
这次真的是把
TypeScript
写成了anyScript
,中间不知道用了多少的类型断言和:any
😟
End
开头已经展示过页面效果啦,就不再测试了 😄