今天分享一下怎么编写上传进度条!
- 首先需要知道怎么监听文件上传进度?
- 然后怎么实现进度动画?
- 怎么实现绑定
antd-form表单
首先需要知道怎么监听文件上传进度?
- 调查中 xhr里面有
onUploadProgress这个方法可以知道上传时时进度,返回一个参数progressEvent有2个字段,progressEvent.loaded / progressEvent.totalpercent就可以知道进度,那这样就很简单了,在api调用接口传入一个回调,代码如下。
const sendOSS = (
params: any,
url: string,
onUploadProgressCallback?: Function
): any => {
return axios({
url: url,
data: params,
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
onUploadProgress: (progressEvent) => {
let percent = ((progressEvent.loaded / progressEvent.total) * 100) | 0
onUploadProgressCallback && onUploadProgressCallback(percent)
},
})
}
然后怎么实现进度动画?
- 进度动画比较简单了,就是设置宽度,然后在当前div css添加
transition: width 0.5s;实现一个动画过度效果,代码如下下
<div
className="progress-line"
style={{ width: percent + '%' }}
></div>
怎么实现绑定 antd-form 表单
首先表单回给组件输入value,onChange 2个方法
- value 就是form给到数据,通过onChange 回调数据,受控组件
const fileUpload: React.FC<
UploadFiles & {
multiple?: boolean
value: Array<UploadListProps>
}
> = (props) => {
const {
uploadFilesProps = {},
children,
onUploadClose,
multiple = false,
formItemStyles = {},
value,
onChange,
} = props
const [fetchSendOssPolicy] = useFileHook({
multiple,
onChange,
value,
})
const { accept } = uploadFilesProps
const defaultUploadFilesProps = {
beforeUpload: async (file: RcFile) => {
console.log(accept)
if (accept) {
const acceptArr = accept.split(',')
if (!acceptArr.includes(file.type)) {
return false
}
}
await fetchSendOssPolicy(file)
return false
},
showUploadList: false,
...uploadFilesProps,
}
const onUploadCloseList = (item: UploadListProps) => {
onChange &&
onChange(value.filter((ele: UploadListProps) => ele.key != item.key))
onUploadClose && onUploadClose(item)
}
return (
<>
<Upload {...defaultUploadFilesProps}>{children}</Upload>
<div style={{ marginTop: 8 }}>
<Row gutter={[12, 12]}>
{value?.map((item: UploadListProps) => {
return (
<Col
{...{ ...formItemStyle, ...formItemStyles }}
key={encodeURIComponent(item.key)}
>
<UploadList
{...item}
onUploadClose={() => onUploadCloseList(item)}
/>
</Col>
)
})}
</Row>
</div>
</>
)
}
//进度条
const AntUploadList = (
item: UploadListProps & {
onUploadClose?: (value: Record<string, any>) => void
rightSlot?: React.ReactNode
readonly?: boolean
}
) => {
const { onUploadClose, rightSlot, readonly = false } = item
const progressDom = useRef<any>()
const progressRafRef = useRef<any>({
dom: null,
})
useEffect(() => {
if (readonly) {
progressDom.current.style = ' display:none'
}
return () => {
window.clearTimeout(progressRafRef.current.dom)
}
}, [item.percent])
const percentageDom = useMemo(() => {
return <div className="percentage">{item.percent}%</div>
}, [item.percent])
useEffect(() => {
if (item.percent == 100) {
progressRafRef.current.dom = setTimeout(() => {
progressDom.current.style = ' display:none'
}, 300)
}
}, [item.percent])
return (
<div className={'progress-item'}>
<div
className="file"
style={{ marginLeft: 9, width: 'calc(100% - 130px)' }}
>
<div className="progress-name">
<div className="ellipsis">
<Tooltip placement="top" title={item.name}>
{item.name}
</Tooltip>
</div>
<div
style={{
display: 'inline-block',
marginLeft: 10,
color: 'rgba(31, 35, 28, 0.6)',
}}
>
<div> {(item.size ? item.size : 0 / 1024).toFixed(2)} KB</div>
</div>
</div>
<div className="progress" ref={progressDom}>
<div className="progress-bg">
<div
className="progress-line"
style={{ width: item.percent + '%' }}
></div>
</div>
{percentageDom}
</div>
</div>
</div>
)
}