支持表单受控和非受控使用,基于antd upload 进行的二次封装,

使用场景如下图:

1.组件文件夹

2. index.tsx贴代码

import React, { useEffect, useMemo, useState } from 'react';
import { ImageFilesWrapper } from './style';
import type { RcFile, UploadProps } from 'antd/es/upload';
import type { UploadFile } from 'antd/es/upload/interface';
import { message, Modal } from 'antd';
import icon from './img/uil_image_plus.svg';
import { uploadImageFileWithNoToken } from 'requests/fileUpload-requests';
import { addUriPrefixIfNeeded } from 'utils/requests/utils'; // 转化url
import { v4 } from 'uuid';
interface Iprops {
onChange?: (data) => void;
onRemove?: (data) => void;
maxCount?: number; //可上传的图片张数
value?: string[]; // 表单默认值
multiple?: boolean;
}
interface Iflie {
uid: string;
status: string;
url: string;
} //图片上传
export default function ImageUpload(props: Iprops) {
const { onChange, multiple, value, onRemove, maxCount } = props;
// 处理 表单传入的值
const defaultList = useMemo(() => {
if (value?.length) {
let list: Iflie[] = [];
value?.map(v => {
list.push({
uid: v4(),
status: 'done',
url: addUriPrefixIfNeeded(v),
});
});
return list;
}
}, [value]); const [fileList, setFileList] = useState<any>(defaultList || []); const [previewVisible, setPreviewVisible] = useState(false);
const [previewImage, setPreviewImage] = useState('');
const [previewTitle, setPreviewTitle] = useState(''); const handleCancel = () => setPreviewVisible(false);
const handleChange: UploadProps['onChange'] = async ({
fileList: newFileList,
}) => {
setFileList(newFileList || []);
let urlList: any = [];
newFileList?.map(v => {
if (v?.response?.fileId || v.url) {
urlList.push(v?.response?.fileId || v.url);
}
});
onChange?.(urlList);
}; const getBase64 = (file: RcFile): Promise<string> =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result as string);
reader.onerror = error => reject(error);
}); const handlePreview = async (file: UploadFile) => {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj as RcFile);
}
setPreviewImage(file.url || (file.preview as string));
setPreviewVisible(true);
setPreviewTitle(
file.name || file.url!.substring(file.url!.lastIndexOf('/') + 1),
);
}; async function uploadHeadImg(info) {
try {
const res = await uploadImageFileWithNoToken(info.file);
if (res) {
message.info('上传成功');
info.onSuccess(res, info.file); // 上传成功触发
} else {
message.error('上传失败');
}
} catch (error) {
info.onError(error, undefined, info.file); // 上传失败触发
// @ts-ignore
message.error(error?.message || '上传失败');
console.error(error);
}
} return (
<>
<ImageFilesWrapper
listType="picture-card"
fileList={fileList}
onPreview={handlePreview}
multiple={multiple}
maxCount={maxCount}
accept=".png,.jpg,.jpeg"
beforeUpload={file => {
if (!['image/png', 'image/jpg', 'image/jpeg'].includes(file.type)) {
message.info('仅支持上传png/jpg/jpeg格式的图片');
}
return ['image/png', 'image/jpg', 'image/jpeg'].includes(file.type);
}}
onChange={handleChange}
onRemove={(data: any) => {
console.log(data, 'data,remove');
if (data?.disabled) {
return Promise.resolve(false);
} else {
return onRemove ? onRemove(data) : Promise.resolve(true);
}
}}
customRequest={uploadHeadImg}
>
{((maxCount && fileList?.length < maxCount) || !maxCount) && (
<div className="imgButton">
<img src={icon} alt="" />
<div>添加图片</div>
</div>
)}
</ImageFilesWrapper> <Modal
open={previewVisible}
title={previewTitle}
footer={null}
onCancel={handleCancel}
>
<img alt="example" style={{ width: '100%' }} src={previewImage} />
</Modal>
</>
);
}

3.样式代码

import { Upload } from 'antd';
import styled from 'styled-components/macro'; export const ImageFilesWrapper = styled(Upload)`
text-align: left;
.adm-image-uploader-cell {
width: 60px;
height: 60px;
line-height: 60px;
}
.adm-image-uploader {
}
.upload-finsh {
color: #0ebd73;
margin-right: 10px;
}
.imgButton {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
color: var(--primary-color);
img {
margin-right: 5px;
}
}
`;

4.页面表单使用

        <Form.Item
label="人员头像"
name="headerImg"
rules={[
{
required: false,
},
]}
valuePropName="value"
trigger="onChange"
>
<ImageUpload maxCount={1} />
</Form.Item>

表单初始值赋:

 initialValues={{
headerImg: infoToEdit?.avatarUrl ? [infoToEdit.avatarUrl] : undefined,
}}

react封装图片上传组件的更多相关文章

  1. 微信小程序简单封装图片上传组件

    微信小程序简单封装图片上传组件 希望自己 "day day up" -----小陶 我从哪里来 在写小程序的时候需要上传图片,个人觉得官方提供的 Uploader 组件不是太好用, ...

  2. React后台管理手动封装图片上传组件

    分为两个文件夹,index.js(逻辑文件) styled.js(样式文件) index.js文件,编写完成之后在对应的地方引入即可 import React from "react&quo ...

  3. 基于Node的React图片上传组件实现

    写在前面 红旗不倒,誓把JavaScript进行到底!今天介绍我的开源项目 Royal 里的图片上传组件的前后端实现原理(React + Node),花了一些时间,希望对你有所帮助. 前端实现 遵循R ...

  4. 分享一个react 图片上传组件 支持OSS 七牛云

    react-uplod-img 是一个基于 React antd组件的图片上传组件 支持oss qiniu等服务端自定义获取签名,批量上传, 预览, 删除, 排序等功能 需要 react 版本大于 v ...

  5. vue图片上传组件

    前言:很多项目中都需要用到图片上传功能,而其多处使用的要求,为了避免重复造轮子,让我决定花费一些时间去深入了解,最终封装了一个vue的图片上传组件.现将总结再次,希望有帮助. Layout <d ...

  6. Jquery图片上传组件,支持多文件上传

    Jquery图片上传组件,支持多文件上传http://www.jq22.com/jquery-info230jQuery File Upload 是一个Jquery图片上传组件,支持多文件上传.取消. ...

  7. H5拍照、选择图片上传组件核心

    背景 前段时间项目重构,改成SSR的项目,但之前用的图片选择上传组件不支持SSR(server-side-render).遂进行了调研,发现很多的工具.但有的太大,有的使用麻烦,有的不满足使用需求.决 ...

  8. 图片上传组件webuploader

    前端组件webuploader 当时也是搞了很久参考这种demo,但是没记.现在事后大致总结下.直接上大概代码(我使用asp.net  MVC来做的): 执行顺序:(get)Record/Add——A ...

  9. vux-uploader 图片上传组件

    1.网址:https://github.com/greedying/vux-uploader 2.安装 npm install vux-uploader --save npm install --sa ...

  10. 【antd Vue】封装upload图片上传组件(返回Base64)

    最近需要把上传的图片信息存储到数据库,以base64的方式,需要重新封装一下antd的upload组件 1. 使用方法 引入组件然后配置一下即可使用,配置项包括 defaultImageList,需要 ...

随机推荐

  1. P5733 自动修正

    字符串题解第一弹~ [千万不能错过的原题连接](https://www.luogu.com.cn/problem/P5733) 今天就研究一下这道自动修正问题哈 首先,我们看到了小写转大写的时候,就知 ...

  2. top单核与32C--CPU爆表

    linux的cpu使用频率是根据cpu个数和核数决定的 top, 然后你按一下键盘的1,这就是单个核心的负载,不然是所有核心的负载相加,自然会超过100 单核为100%,服务器是32核的,下面基本用了 ...

  3. ADC采样信号RMS测量值的Verilog实现

    术语"RMS"代表"Root-Mean-Squared".大多数书籍将此定义为"产生与等效直流电源相同的加热效果的交流电量",或者沿着这些线 ...

  4. jmeter使用Java开发自定义函数

    一.前置条件(对jmeter进行二次开发) 本篇通过抽象类AbstractFunction来实现: 1.JMeter提供了接口给用户进行二次开发,其中接口可通过引入 ApacheJMeter_comp ...

  5. DataTable中排序的开启与禁用

    1. 2. orderable设置成true会打开排序功能,设置为false会禁用排序功能.

  6. Python发送飞书消息

    #!/usr/bin/python3.8 # -*- coding:UTF-8 -*- import os, sys sys.path.append(os.path.dirname(os.path.a ...

  7. 正则表达式re.compile()的使用

    re 模块提供了不少有用的函数,用以匹配字符串,比如: compile 函数match 函数search 函数findall 函数finditer 函数split 函数sub 函数subn 函数re ...

  8. 关于 echarts 使用 geo 制作地图 tooltip 不显示问题(转)

    原文地址 我之前遇到过这问题,单独设置 tooltip 没效果,geo 下面也有 tooltip 属性,但是也不管用,网上查了一下说 geo 不支持 tooltip 提示框显示,就自己根据 echar ...

  9. IDEA debug时拷贝数据 Evaluate Expression窗口

    今日份鸡汤:别人再好,也是别人.自己再不堪,也是自己,独一无二的自己.只要努力去做最好的自己,一生足矣.为自己的人生负责,为自己的梦想买单. 用IDEA调试时候经常需要拷贝变量值出来排查,特别是数据结 ...

  10. JiaoZiVideoPlayer模拟用户点击,切换播放引擎!~

    默认播放及模拟用户点击播放按钮 jzvideoPlayerStandard.startButton.performClick() 切换播放引擎及使用Ijkplayer JZVideoPlayer.se ...