封裝 antd-upload

剛到杭州感覺略疲憊开财,后臺大佬(世界上最好的語言的使用者)表示我們的上傳圖片要做成前端直接上傳七牛,然后把地址給后端惹悄。春叫。。泣港。emmm 原來最優(yōu)秀的后臺都會偷懶啊暂殖。

那我只能基于antd的upload封裝出一個比較適用于圖片上傳七牛,oss当纱,后臺的組件了呛每,這是 antd-upload地址

剛學(xué)會hooks并且應(yīng)用于自己的項目,瞎子過河摸索著過唄
    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 = () => { // 這里是在圖片上傳之后 調(diào)用此函數(shù)將qiNiuToken改變 以觸發(fā)重新請求
        setQiNiuToken(null);
    }
  <FormItem>
       <Text><Text type="danger">*</Text>主辦單位證件</Text>
          {
             getFieldDecorator(
                'cert', {
                   valuePropName: 'file',
                   getValueFromEvent: normFile,
                   rules: [
                    {
                       required: true,
                       message: '請上傳主辦單位證件!'
                     }
                    ]
                }
              )(
               <CustomUpload
                 className="icbc-legal-upload"
                 placeholder="請上傳營業(yè)執(zhí)照或三證合一掃描件"
                 action={qiniuAction}
                 data={
                        {
                          token: qiNiuToken
                        }
                 }
                 onUploadEnd={onUploadEnd}
               />
        )
     }
</FormItem>
接下來是重頭戲 組件
  // 因為Form裝飾器getFieldDecorator的某些屬性不支持函數(shù)組件 這里使用類組件的形式
import React, { Component } from 'react';

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

// 圖片轉(zhuǎn)換base64   以及上傳前的檢測
import { getBase64, filterPic } from 'lib/utils';

import './index.scss';

class CustomUpload extends Component {
    // imageUrl 是上傳圖片后轉(zhuǎn)base64在頁面中的顯示
    // previewVisible 查看大圖的開關(guān)
    // 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);// 這里由于要將請求的結(jié)果作為getFieldDecorator裝飾器的value 調(diào)用傳入的callback 實際調(diào)用的就是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 此次請求攜帶的參數(shù)  傳七牛需要帶token  由父組件傳入  action  hostapi
        const { className, placeholder, onChange, data = {}, action } = this.props;

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

        return (
            <div className="upload-main" onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
                <div className={`mask ${showMask ? 'showMask' : ''}`}>
                    <Icon type="eye" onClick={this.handlePreview} />
                    <Icon type="delete" onClick={this.handleDelete} />
                </div>
                <Upload
                    listType="picture-card"
                    className={`uploader ${className}`}
                    showUploadList={false}
                    action={action}
                    data={data}
                    beforeUpload={this.beforeUpload}
                    onChange={info => this.handleChange(info, onChange)}
                >
                    {
                        imageUrl ? <img src={imageUrl} alt="pic" style={{ width: '100%', height: '100%' }} /> : <div>
                            <Icon type={loading ? 'loading' : 'plus'} />
                            <div className="ant-upload-text">{placeholder || 'Upload'}</div>
                        </div>
                    }

                </Upload>
                <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel} width={600}>
                    <img alt="example" src={imageUrl} style={{ maxWidth: '100%' }} />
                </Modal>
            </div>
        )
    }
}
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;
            }
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晨横,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子箫柳,更是在濱河造成了極大的恐慌手形,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悯恍,死亡現(xiàn)場離奇詭異库糠,居然都是意外死亡,警方通過查閱死者的電腦和手機涮毫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門瞬欧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人罢防,你說我怎么就攤上這事艘虎。” “怎么了咒吐?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵野建,是天一觀的道長属划。 經(jīng)常有香客問我,道長贬墩,這世上最難降的妖魔是什么榴嗅? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮陶舞,結(jié)果婚禮上嗽测,老公的妹妹穿的比我還像新娘。我一直安慰自己肿孵,他們只是感情好唠粥,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著停做,像睡著了一般晤愧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛉腌,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天官份,我揣著相機與錄音,去河邊找鬼烙丛。 笑死舅巷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的河咽。 我是一名探鬼主播钠右,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼忘蟹!你這毒婦竟也來了飒房?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤媚值,失蹤者是張志新(化名)和其女友劉穎狠毯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體褥芒,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡垃你,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了喂很。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡皆刺,死狀恐怖少辣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情羡蛾,我是刑警寧澤漓帅,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響忙干,放射性物質(zhì)發(fā)生泄漏器予。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一捐迫、第九天 我趴在偏房一處隱蔽的房頂上張望乾翔。 院中可真熱鬧,春花似錦施戴、人聲如沸反浓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雷则。三九已至,卻和暖如春肪笋,著一層夾襖步出監(jiān)牢的瞬間月劈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工藤乙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留猜揪,地道東北人。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓湾盒,卻偏偏與公主長得像湿右,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子罚勾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354