上次写了一个vue组件的实现,这次我们同样来写一个react的图片上传组件,同样的,也是基于antd进行封装。
react与vue不同,没有双向绑定,以antd为例,form表单组件主要通过value进行传值,然后通过onChange的回调,对外部值进行更新。同样的为了使组件在非Form场景下依旧可用,这里我们依旧是通过定义一个内部的value对象来实现。
import {Button, Divider, Image, Upload} from "antd";
import {UploadOutlined} from "@ant-design/icons";
import styles from "./index.module.less";
import {useEffect, useState} from "react";
const PictureUpload = ({value, onChange, name, uploadAction}) => {
const [scopeValue, setScopeValue] = useState(value);
useEffect(() => {
if (value !== scopeValue) {
setScopeValue(value);
}
}, [value]);
useEffect(() => {
if (onChange) {
onChange(scopeValue);
}
}, [scopeValue]);
const handleUpload = (param) => {
if (!param.file) {
return;
}
if (uploadAction) {
let form = new FormData();
form.append(name, param.file);
uploadAction.then((res) => {
setScopeValue(res.url)
})
}
}
const handleClean = () => {
setScopeValue('')
}
return <div className={styles.pictureUpload}>
{!scopeValue && <Upload name="avatar"
listType="picture-card"
className="avatar-uploader"
showUploadList={false} customRequest={handleUpload}>
<UploadOutlined/>
</Upload>}
{scopeValue && <div className={styles.pictureUploadImage}>
<Image src={scopeValue}/>
<div className={styles.pictureUploadImageTooltip}>
<Upload customRequest={handleUpload}><Button type="text">更换</Button></Upload>
<Divider type="vertical"/>
<Button type="text" onClick={handleClean}>删除</Button>
</div>
</div>}
</div>
}
export default PictureUpload
react组件与vue最大的区别是没有 双向绑定的概念,而vue的双向绑定,其实也是通过监听值的变化实现的。
没有值的时候,依旧是一个朴素的上传框
上传一张图片试试
以上都是只是表现形式。但是从实现来看react是要比vue更加优雅的。