技术栈
AntDesign 版本 : 3x
效果图如下
官网示例给的是标准上传模式, 此处用的是自定义上传模式(customRequest)
代码
子组件代码 ↓
import React, {
useState, useImperativeHandle } from 'react'
import PropTypes from 'prop-types'
import {
Modal, Upload, Icon } from 'antd'
import styles from './ImgUpload.less'
import {
uploadFunc } from '../../common/uploadFunc'
const getBase64 = file =>
new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => resolve(reader.result)
reader.onerror = error => reject(error)
})
const ImgUpload = (props, ref) => {
// dataList - 父组件传入的图片列表, 数据接口可参考官网
// maxCount - 父组件传入的上传图片数量的最大值, 可控制单张或多张图片
// disabled - 父组件传入的控制组件是否禁止上传
// handleMediaResource - 与父组件进行数据通信
const {
dataList, maxCount, type, disabled, handleMediaResource } = props
const [previewOpen, setPreviewOpen] = useState(false)
const [previewImage, setPreviewImage] = useState('')
const [previewTitle, setPreviewTitle] = useState('')
const [fileList, setFileList] = useState(dataList)
const handleCancel = () => setPreviewOpen(false)
// 父组件提交数据时, 重置该子组件数据
useImperativeHandle(ref, () => ({
clearUploadList }))
const clearUploadList = () => {
setFileList([])
}
// 是否允许显示删除按钮
// 只读时, 不允许用户进行删除操作
const showUploadList = {
showRemoveIcon: disabled ? false : true }
// 图片点击放大查看
const handlePreview = async file => {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj)
}
setPreviewImage(file.url || file.preview)
setPreviewOpen(true)
setPreviewTitle(
file.name || file.url.substring(file.url.lastIndexOf('/') + 1)
)
}
const handleChange = ({
fileList: newFileList }) => {
}
// base64转Blob
const base64ToBlob = code => {
const parts = code.split(';base64,')
const contentType = parts[0].split(':')[1]
const raw = window.atob(parts[1])
const rawLength = raw.length
const uInt8Array = new Uint8Array(rawLength)
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i)
}
return new Blob([uInt8Array], {
type: contentType })
}
// 自定义上传逻辑
const customRequest = async options => {
const {
file, filename, data } = options
// uploadFunc 是服务器上传操作
const base64 = await getBase64(file)
const suffixs = ['jpg', 'jpeg', 'png']
const usage = 'picture'
uploadFunc(file, suffixs, usage)
.then(res => {
const newImgList = [
...fileList,
{
uid: file.uid,
name: file.name,
status: 'done',
url: res.path,
// url: URL.createObjectURL(base64ToBlob(base64)),
lastModified: file.lastModified,
lastModifiedDate: file.lastModifiedDate,
originFileObj: file,
percent: 100,
thumbUrl: base64,
type: file.type,
},
]
// 更新图片列表数据
setFileList(newImgList)
if (newImgList.length > 0) {
handleMediaResource({
type, fileList: newImgList })
}
})
.catch(err => {
const newFileList = [
...fileList,
{
uid: file.uid,
name: file.name,
status: 'error',
url: file.path,
lastModified: file.lastModified,
lastModifiedDate: file.lastModifiedDate,
originFileObj: file,
percent: 100,
type: file.type,
},
]
setFileList(newFileList)
})
}
const props2 = {
accept: props.acceptType,
// 删除已上传数据
onRemove: file => {
const index = fileList.indexOf(file)
const newFileList = fileList.slice()
newFileList.splice(index, 1)
setFileList(newFileList)
},
}
const uploadButton = (
<div>
<Icon style={
{
fontSize: '18px' }} type="upload" />
<div
style={
{
marginTop: 8,
}}
>
Upload
</div>
</div>
)
return (
<div>
<Upload
{
...props2}
listType="picture-card"
fileList={
fileList}
disabled={
disabled}
showUploadList={
showUploadList}
onPreview={
handlePreview}
onChange={
handleChange}
customRequest={
customRequest}
>
{
fileList.length >= maxCount ? null : uploadButton}
</Upload>
<Modal
centered
width={
700}
// 注意 : 这儿3.x展示modal属性是visible,5.x是open
visible={
previewOpen}
title={
previewTitle}
footer={
null}
onCancel={
handleCancel}
>
<img
alt="example"
style={
{
width: '100%',
}}
src={
previewImage}
/>
</Modal>
</div>
)
}
export default React.forwardRef(ImgUpload)
父组件(部分)代码 ↓
// 通过ref向子组件传递事件
const uploadImgComRef = React.createRef(null)
// 提交时清除图片组件数据
const onSubmitFn = e => {
uploadImgComRef.current.clearUploadList()
}
// 上传组件
<ImgUpload
ref={
uploadImgComRef}
acceptType=".jpg,.jpef,.png"
maxCount="1"
dataList={
imgDataList}
disabled={
editType == 'view' ? true : false}
handleMediaResource={
handleMediaResource}
/>