AntDesign上传组件upload二次封装+全局上传hook使用

文章目录

  • 前言
  • a-upload组件二次封装
    • 1. 功能分析
    • 2. 代码+详细注释
    • 3. 使用到的全局上传hook代码
    • 4. 使用方式
    • 5. 效果展示
  • 总结


前言

在项目中,ant-design是我们常用的UI库之一,今天就来二次封装常用的组件a-upload批量上传组件,让它用起来更方便。

a-upload组件二次封装

1. 功能分析

(1)自定义展示区,可按UI规范自定义展示
(2)上传失败,过滤成功的文件,重新赋值展示,不展示失败的文件
(3)上传之前的校验通过配置,在组件内统一管理
(4)通过传入defaultValue prop,进行初始化数据显示
(5)通过传入beforeChange prop,可以根据外部promise上传文件返回的结果,做一些处理

2. 代码+详细注释

// @/components/uploads/index.tsx
<template><a-upload v-model:file-list="state.fileList" :accept="accept" list-type="picture" class="avatar-uploader" multiple :max-count="3" :before-upload="beforeUpload" :customRequest="handlerUploadFile" @change="handlerChange" @remove="handlerRemove"><a-button><UploadOutlined />选择附件</a-button><template #itemRender="{ file, actions }"><div class="cd-upload-list"><LoadingOutlined class="cd-upload-list-loading" v-if="file.status === 'uploading'" /><template v-else><a class="cd-upload-list-item" :href="file?.response || file?.url" target="_blank"><img v-if="isImage(file?.response)" class="cd-upload-list-img" :src="file?.response || file?.url" alt="" /><FileOutlined v-else class="cd-upload-list-icon" /><span class="cd-upload-list-name">{{ file.name }}</span></a></template><a class="cd-upload-list-remove" href="javascript:;" @click="actions.remove"> <DeleteOutlined /></a></div></template></a-upload>
</template>
<script lang="ts" setup>
import { reactive, ref, Ref, watch, PropType } from "vue";
import { message } from "ant-design-vue";
import { UploadOutlined, DeleteOutlined, FileOutlined, LoadingOutlined } from "@ant-design/icons-vue";
import type { UploadProps, UploadChangeParam } from "ant-design-vue";
import type { UploadRequestOption } from "ant-design-vue/es/vc-upload/interface";
/*** 类型声明*/
type ProgressProps = UploadProps["progress"];
type uploadFunProps<T> = Omit<UploadRequestOption<T>, "onSuccess"> &Omit<UploadRequestOption<T>, "onError"> & {onSuccess: any;onError: any;};
/*** @param data 文件地址* 是否是图片*/
const isImage = (data: string | undefined) => {if (!data) return false;const fileExtensions = [".png", ".jpg", ".jpeg"];return fileExtensions.some((extension) => data.endsWith(extension));
};
/*** props*/
const props = defineProps({val: {type: Array,default: () => [],},accept: {type: String,default: ".doc,.docx,.xlsx,.xls,.pdf,.jpg,.png,.jpeg",},max: {type: Number,default: 1,},size: {type: Number,default: 2,},defaultValue: {type: Array,default: () => [],},format: Function,text: {type: String,default: "",},params: {type: Object,default: {},},beforeChange: {type: Function as PropType<(options: any) => Promise<any>>,},
});
/*** emit*/
const emit = defineEmits(["update:val", "upload", "remove"]);
/*** state*/
type PreviewState = {fileList: UploadProps["fileList"];loading: boolean;imageUrl: string;dataList: any[];
};
const state = reactive<PreviewState>({fileList: [],loading: false,imageUrl: "",// 数据文件dataList: [],
});
/*** 文件状态改变时的回调*/
const handlerChange = ({ file, fileList }: UploadChangeParam) => {const status = file.status;if (status === "uploading") {}if (status === "done") {}// 上传失败,过滤成功的文件,重新赋值展示if (!status || status === "error") {const files = fileList.filter((item: any) => item.status === "done");state.fileList = files;}
};
/*** 上传之前检查文件* @param file 文件对象* @returns boolean*/
const beforeUpload = (file: File) => {const type = file.type.split("/")[1];if (props.accept.indexOf(type) === -1) {message.error(`请上传${props.accept}格式文件`);return false;}const maxSize = file.size / 1024 / 1024 < props.size;if (!maxSize) {message.error(`图片大小须小于${props.size}MB`);return false;}return type && maxSize;
};
/*** 上传进度* @param progressEvent 进度对象*/
const progress: ProgressProps = {};
/*** 上传*/
const handlerUploadFile = (options: uploadFunProps<unknown>) => {props?.beforeChange &&props.beforeChange({ file: options.file, params: props.params }).then((res: any) => {message.success(`上传成功`);console.log("res777", res);if (res?.url) {options.onSuccess(res.url, options.file);}}).catch(() => {message.error(`上传失败`);options.onError();});
};
/*** 删除文件的回调* @param file 文件对象*/
const handlerRemove = (file: File) => {emit("remove", file);
};/*** 初始值*/
const initValue = (list: string[]) => {const file = [] as any[];list.forEach((item: string) => {file.push({status: "done",url: item,});});// 更新state.fileList = file;
};
watch(() => props.defaultValue,(val: any) => {if (!val || (val && !val.length)) {return false;}initValue(val);},{ immediate: true }
);
</script>
<style lang="scss" scoped>
.cd-upload-list {display: flex;justify-content: space-between;position: relative;height: 66px;padding: 8px;border: 1px solid #d9d9d9;border-radius: 8px;margin-top: 8px;.cd-upload-list-loading {font-size: 20px;}.cd-upload-list-item {display: flex;align-items: center;.cd-upload-list-img {width: 50px;height: 50px;margin-right: 10px;}.cd-upload-list-icon {font-size: 20px;margin-right: 10px;}.cd-upload-list-name {}}.cd-upload-list-remove {display: flex;align-items: center;font-size: 20px;}
}
</style>

3. 使用到的全局上传hook代码

/*** api*/
import { uploadImage } from "@/api/index";
/*** 上传资源全局hook* @returns */
export function useUploadImage() {const useUploadImageBeforeChange = ({ file, params }: { file: File; params: Record<string, any> }) => {return new Promise((resolve, reject) => {// 实例化表单对象const form = new FormData();// 表单添加 files 字段for (let key in params) {form.append(key, params[key]);}form.append("multipartFiles", file);uploadImage(form).then((res: any) => {const result = res && res.length;resolve(result ? res[0] : null);}).catch(() => {reject();});});};return {useUploadImageBeforeChange,};
}

4. 使用方式

// 引入组件,以及全局上传hook
import Upload from "@/components/upload/index.vue";
import { useUploadImage } from "@/hook/index";
const { useUploadImageBeforeChange } = useUploadImage();
// 使用
const defaultValue: string[] = ref(["http://xxx.pdf"]);<Upload :defaultValue="defaultValue" :size="5" :params="{ fileType: 'xxxxxx' }" :before-change="useUploadImageBeforeChange" />

5. 效果展示

(1)上传
在这里插入图片描述
(2)预览、删除
在这里插入图片描述


总结

接下来会继续分享ant-design常用组件二次封装使用,请持续关注。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/868368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Cloud: Nacos配置中心与注册中心的使用

一、配置中心(配置管理) 配置中心是一种集中化管理配置的服务。它的主要作用包括集中管理配置信息&#xff0c;将不同服务的配置信息集中存储和管理&#xff1b;支持动态更新配置&#xff0c;通过操作界面或 API 无需重启服务即可应用最新配置信息&#xff1b;实现配置信息共享…

如何解决亚马逊环境技术问题?自养号测评助力下单成功率飙升

在构建针对测评任务的环境系统时&#xff0c;确保系统的稳定性和操作成功率至关重要。面对市场上纷繁复杂的解决方案&#xff0c;如虚拟机、模拟器、GCS服务、云手机及VPS等&#xff0c;虽选择众多&#xff0c;但往往伴随着高昂成本与低成功率的挑战。因此&#xff0c;构建一个…

数据库课设---酒店管理系统(MySQL、VBNet)

目录 一. 知识技术 二. 需求分析 2.1 功能需求 2.2 数据需求 三. 数据流图与数据字典 3.1 数据流图 3.1.1 业务流图 3.1.2 数据流图 3.1.3 关系图 3.2 数据字典 四. 数据库设计 4.1 概念模型设计 4.2 逻辑模型设计 4.3 数据库实现 …

网络规划与设计————期末复习

一、选择题&#xff08;每题1分&#xff09; 1、光纤线组建的标准以太网是______。 A.10BASE-5 B.10BASE-2 C.10BASE-T D.10BASE-F 其实也很好记&#xff0c;光纤的英文是 "Fiber Optic"&#xff0c;双绞线的英文是 "Twisted Pair"。 5呢…

苹果电脑压缩软件哪个好用一些? mac电脑用什么压缩软件 mac电脑压缩文件怎么设置密码

压缩软件是Mac电脑必不可少的工具&#xff0c;虽然Mac系统自带了一款“归档实用工具”&#xff0c;但是其功能实在匮乏&#xff0c;若你需要加密压缩文件或者把文件压缩成指定格式&#xff0c;那么该工具无法满足你的需求。Mac用户应该怎么选择压缩软件呢&#xff1f;本文就来告…

股票数据分析(K线图、均值图、MACD图、RSI图)--股票日数据

数据 数据是上证指数日行情数据&#xff0c;股票代码000002.sz&#xff0c;原始数据shdata示例如下&#xff1a; 读取数据&#xff1a; import numpy as np import pandas as pd import mplfinance as mpf import matplotlib.pyplot as plt from datetime import datetime imp…

出书流程/专著/合著/年内下号

出书流程/专著/合著/年内下号 年内书号&#xff0c;年内书号&#xff0c;年内书号 独著&#xff0c;合著&#xff0c;一书一号&#xff0c;正规出版。省级出版社&#xff0c;国家级出版社&#xff0c;985&#xff0c;211大学出版社&#xff0c;百佳出版社&#xff0c;均可安排…

刷题之删除有序数组中的重复项(leetcode)

删除有序数组中的重复项 这题简单题&#xff0c;双指针&#xff0c;一个指针记录未重复的数的个数&#xff0c;另一个记录遍历的位置。 以下是简单模拟&#xff0c;可以优化&#xff1a; class Solution { public:int removeDuplicates(vector<int>& nums) {int l0…

JVM专题之G1垃圾收集器下

索引(记录)的源码的工作流程图如下: CSet(Collection Set 回收集合) 收集集合(CSet)代表每次GC暂停时回收的一系列目标分区。在任意一次收集暂停中,CSet所有分区都会被释放,内部存活的对象都会被转移到分配的空闲分区中。因此无论是年轻代收集,还是混合收集,工作的机…

主流电商平台营销中大数据的应用◆

随着经济的不断发展&#xff0c;网络信息技术不断加强&#xff0c;电子商务和大数据的蓬勃发展极大地方便了人们的生活。本文章主要阐述大数据分析与电商营销的含义、大数据分析在电子商务营销中的应用&#xff0c;以及该应用的作用和存在哪些不足及解决方法。探究大数据分析在…

Geoserver源码解读六 插件(怎么在开发模式下使用)

系列文章目录 Geoserver源码解读一 环境搭建 Geoserver源码解读二 主入口 Geoserver源码解读三 GeoServerBasePage Geoserver源码解读四 REST服务 Geoserver源码解读五 Catalog Geoserver源码解读六 插件&#xff08;怎么在开发模式下使用&#xff09; 文章目录 系列文…

希亦、小吉、觉飞内衣洗衣机值得买吗?王牌对决测评还不来看看!

内衣洗衣机是近几年新兴的家电产品&#xff0c;以清洁效果好、除菌能力强&#xff0c;被很多人种草入手了&#xff01;但网上有不少人虽感兴趣&#xff0c;但不清楚如何选。担心买到质量差&#xff0c;清洗不干净的产品。所以为了帮助大家可以更好的了解哪个品牌的内衣洗衣机比…

latex改写字体和字号

文章目录 字体使用宏包设置命令声明命令 字号例子设置特定字号 设置行间距用\setlength{\baselineskip}{24pt}设置\renewcommand{\baselinestretch}{2} \selectfont中文行距&#xff08;{ctex}&#xff09; 补充&#xff1a; 字体 使用宏包 \usepackage{ctex}设置命令 只对确…

04-Haproxy搭建Web群集

理论讲解 Haproxy 是目前比较流行的一种群集调度工具&#xff0c;同类群集调度工具有很多&#xff0c;如LVS 和Nginx。相比较而言&#xff0c;LVS 性能最好&#xff0c;但是搭建相对复杂:Nginx的upstream模块支持群集功能&#xff0c;但是对群集节点健康检查功能不强&#xff…

大模型面试笔试常见问题汇总(精心准备)

1 GPT和Bert的区别? 1.模型结构和训练方式 BERT通过掩码语言模型(Masked Language Model, MLM)和下一句预测(Next Sentence Prediction, NSP)任务进行训练: 掩码语言模型(MLM):在输入序列中,BERT随机掩盖一些词语,并要求模型预测这些被掩盖的词语。这使得BERT能够学…

WordPress作品设计素材图片站资讯文章教程uigreat主题

主题介绍 uigreat主题是一款wordpress作品主题&#xff0c;发布设计作品素材文章&#xff0c;适合作品展示、设计等站点使用等&#xff0c;这款主题都非常合适。 1、自适应设计&#xff0c;PC、平板、手机等均可正常浏览&#xff1b; 2、图片缩略图可自定义高度&#xff0c;主…

阶段三:项目开发---民航功能模块实现:任务18:指挥航空公司架次与延误率占比

任务描述 内 容&#xff1a;在前面的“使用Spark清洗统计业务数据并保存到数据库”任务中&#xff0c;已经通过Spark Streaming 清洗程序&#xff0c;将Kafka中Topic为“task_Aftn”的报文数据&#xff0c;经过数据清洗后&#xff0c;保存到了MySQL数据库中&#xff1b;本节任…

工程仪器振弦采集仪的设计与研发进展

工程仪器振弦采集仪的设计与研发进展 工程仪器振弦采集仪是一种用于测量和记录物体振动参数的仪器。它能够实时采集物体的振动信号&#xff0c;并通过内部的传感器将振动信号转化为电信号&#xff0c;然后进行信号放大和处理&#xff0c;最终以数字形式显示或存储。 河北稳控科…

【源码下载】瓦房店农村电商大数据平台模板

技术详细实现可在评论区留言。 概述 用 echarts 和 jquery 实现的大屏模板效果。 部分代码展示&#xff0c;访问 dt.sim3d.cn 获取源码&#xff1a; (function($){$.extend({initMapChartPath : function(options){var defs {domId : ,mapName:china,mapCenter:["5…

iPhone也能做电子书?不要低估了iPhone处理PDF文件的能力

在数字化时代&#xff0c;我们越来越依赖智能手机来处理日常任务&#xff0c;其中iPhone以其出色的功能和用户友好的界面&#xff0c;成为了许多人的首选。 它不仅仅是通讯工具&#xff0c;更是一个强大的个人数字助理&#xff0c;能够实时扫描文件、制作PDF电子书&#xff0c…