封装 antd-upload

刚到杭州感觉略疲惫,后台大佬(世界上最好的语言的使用者)表示我们的上传图片要做成前端直接上传七牛,然后把地址给后端。。。。emmm 原来最优秀的后台都会偷懒啊。

那我只能基于antd的upload封装出一个比较适用于图片上传七牛,oss,后台的组件了,这是 antd-upload地址

刚学会hooks并且应用于自己的项目,瞎子过河摸索着过呗
    import React, { useEffect, useState } from 'react';

    const [qiNiuToken, setQiNiuToken] = useState(null);

    const qiniuAction = 'http://upload.qiniup.com';

    const normFile = info => {  // 将upload的值作为装饰器的value

        return (info.file && info.file.response) || undefined;

    }

    useEffect(() => {  // 这里是在didmount和qiNiuToken改变的时候 重新去尝试请求新的qiniu toekn

        if (qiNiuToken) return;

        const asyncRequest = async () => {

            const token = await appApi.receiveQiniuToken();

            setQiNiuToken(token);

        }

        asyncRequest();

    }, [qiNiuToken])

    const onUploadEnd = () => { // 这里是在图片上传之后 调用此函数将qiNiuToken改变 以触发重新请求
        setQiNiuToken(null);
    }
  
       *主办单位证件
          {
             getFieldDecorator(
                'cert', {
                   valuePropName: 'file',
                   getValueFromEvent: normFile,
                   rules: [
                    {
                       required: true,
                       message: '请上传主办单位证件!'
                     }
                    ]
                }
              )(
               
        )
     }

接下来是重头戏 组件
  // 因为Form装饰器getFieldDecorator的某些属性不支持函数组件 这里使用类组件的形式
import React, { Component } from 'react';

import { Upload, Icon, message, Modal } from 'antd';

// 图片转换base64   以及上传前的检测
import { getBase64, filterPic } from 'lib/utils';

import './index.scss';

class CustomUpload extends Component {
    // imageUrl 是上传图片后转base64在页面中的显示
    // previewVisible 查看大图的开关
    // showMask 自己写的上传图片后的mask  可以查看大图以及删除图片
    constructor(props) {
        super(props);
        this.state = {
            imageUrl: '',
            loading: false,
            previewVisible: false,
            showMask: false
        }
    }
    /**
     * export const filterPic = pic => {
            let content = '';
            const isJpgOrPng = pic.type === 'image/jpeg' || pic.type === 'image/png';
            if (!isJpgOrPng) {
                content = ' 请上传JPG/PNG文件!';
            }
            const isLt2M = pic.size / 1024 / 1024 < 10;
            if (!isLt2M) {
                content = '图像必须小于10MB!';
            }
            return content;
        }
     */
    // 上传图片之前对图片进行检测  大小 类型
    beforeUpload = file => {
        const content = filterPic(file);
        if (content) {
            message.error(content);
            return false;
        }
        return true;
    }
    // 处理上传中的步骤 done 为上传完成
    handleChange = (info, callback) => {
        if (info.file.status === 'uploading') {
            this.setState({ loading: true });
            return;
        }
        if (info.file.status === 'done') {
            const { onUploadEnd } = this.props;
            onUploadEnd(); // 上传完成后通知父组件 可以做刷新七牛token的操作
            callback&&callback(info);// 这里由于要将请求的结果作为getFieldDecorator装饰器的value 调用传入的callback 实际调用的就是getValueFromEvent
            getBase64(info.file.originFileObj, imageUrl => {
                this.setState({
                    imageUrl,
                    loading: false
                })
            });
        }
    };
    onMouseEnter = () => { // 自己写的一些动画 略简陋
        const { imageUrl } = this.state;
        if (imageUrl) {
            this.setState({
                showMask: true
            })
        }
    }
    onMouseLeave = () => {
        this.setState({
            showMask: false
        })
    }
    handlePreview = file => {  // 查看大图
        this.setState({
            previewVisible: true
        });
    };
    handleDelete = () => { // 删除图片
        const { onChange } = this.props;
        Modal.confirm({
            title: '提示',
            content: '确定要删除此图片?',
            okText: '确定',
            cancelText: '取消',
            onOk: () => {
                this.setState({
                    imageUrl: false
                }, () => {
                    onChange({}) //删掉装饰器里的val
                });
            }
        });

    }
    // 取消查看大图
    handleCancel = () => this.setState({ previewVisible: false });

    render() {
        // data 此次请求携带的参数  传七牛需要带token  由父组件传入  action  hostapi
        const { className, placeholder, onChange, data = {}, action } = this.props;

        const { loading, imageUrl, previewVisible, showMask } = this.state;

        return (
            
this.handleChange(info, onChange)} > { imageUrl ? pic :
{placeholder || 'Upload'}
}
example
) } } export default CustomUpload;
index.scss 送给连样式都懒得写的你
  .upload-main{
    position: relative;
    width: 300px;
    height: 202px;
    .mask{
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        background: #000;
        opacity: 0;
        transition: all .3s;
        visibility: hidden;
        display: flex;
        justify-content: center;
        align-items: center;
        &.showMask{
            opacity: .4;
            visibility: visible;
            .anticon{
                cursor: pointer;
                margin-right: 10px;
                font-size: 20px;
                color: #fff;
            }
        }
    }
}

你可能感兴趣的:(封装 antd-upload)