使用Ant Design的Upload上傳刪除預覽照片,以及上傳圖片狀態一直處於uploading的解決方法。


一、界面構建

  1、創建index父組件

import React from "react";
import { Form } from "antd";
import UploadComponent from "./UploadComponent";
export default () => {
  const [form] = Form.useForm();
  return (
    <Form
      form={form}
      initialValues={
        {
          'uploadPhoto': []
        }
      }
    >
      <Form.Item name="uploadPhoto">
        <UploadComponent />
      </Form.Item>
    </Form>
  );
};

  2、創建UploadComponent子組件

import React, { useState, useEffect } from "react";
import { Upload } from 'antd';
import { PlusOutlined } from "@ant-design/icons";
export default (props: any) => {
  console.log(props)
  const [fileList, setFileList] = useState<any>([])      //展示默認值
  const handleChange = ({ file, fileList }: any) => {};
  const uploadButton = (
    <div>
      <PlusOutlined />
      <div className="ant-upload-text">Upload</div>
    </div>
  );
  return (
    <Upload
      listType="picture-card"
      fileList={fileList}
      onChange={handleChange}
      action={'這里是你上傳圖片的地址'}
    >
      {fileList.length >= 8 ? null : uploadButton}
    </Upload>
  );
};

  這樣一個簡單界面就構造完成了,通過打印子組件的props,我們可以看到,父組件給子組件通過prop傳遞了一個對象,該對象中有value:子組件的默認值,id:FormItem的name,onChange:onChange事件

  

注:1、Form表單以及Upload請參考Ant Design官方文檔
  2、因后台返回數據格式不同,所以fileList的設置也不同,本文僅供參考。
  3、本文后台返回的數據格式為:[{id:id1,imgUrl:imgUrl1},...],上傳圖片成功后,返回的也是一個key值,string類型,比如:qwertyuidsa151sad

二、設置upload的fileList

  上傳圖片后,下次再進入該頁面時,Form就會有initialValues默認值,此時upload就要展示默認值中的圖片。

  fileList是一個數組,數組中是n個對象,每個對象都包含 uid:上傳圖片的idname:上傳圖片的名字status:上傳圖片的狀態url:圖片路徑。想展示圖片就必須要設置 uid,status,url。也可以在該對象中增加自己所需要。
  當子組件的props.value變化時,就需要更新fileList,使用useEffect即可。具體代碼如下
useEffect(() => {
    if (props.value) {
      let newFileList = props.value.map((item: any) => {
        return {
          uid: item.id || item.uid,      //存在id時,使用默認的id,沒有就使用上傳圖片后自動生成的uid
          status: 'done',            //將狀態設置為done  
          url: 'https://image/'+item.imgUrl,  //這里是展示圖片的url,根據情況配置
          imgUrl: item.imgUrl,  //添加了一個imgUrl,保存Form時,向后台提交的imgUrl,一個key值
        }
      })
      setFileList(newFileList)
    }
 }, [props])

三、觸發父組件傳遞的onChange

  當子組件每次上傳圖片或者刪除圖片時,都需要觸發父組件的Onchange事件,來改變Form表單的值。自定義一個triggerChange函數,上傳成功或者刪除圖片時,通過triggerChange來觸發onChange

  const triggerChange = (value: any) => {
    const onChange = props.onChange;  
    if (onChange) {
      onChange(value);        //將改變的值傳給父組件
    }
  };

四、file常用的status

  1、uploading:上傳中

  2、done:上傳成功

  3、error:上傳錯誤

  4、removed:刪除圖片

五、上傳圖片

  上傳圖片時,觸發Upload的onChange事件

  const handleChange = ({ file, fileList }: any) => {
  //file:當前上傳的文件
  //通過map將需要的imgUrl和id添加到file中 fileList = fileList.map((file: any) => { if (file.response) { file.id = file.uid; file.imgUrl = file.response.data.key  //請求之后返回的key } return file; }); if (file.status !== undefined) { if (file.status === 'done') { console.log('上傳成功') triggerChange(fileList); } else if (file.status === 'error') { console.log('上傳失敗') } } }

  這樣之后,會發現上傳圖片的狀態一直是uploading狀態,這是因為上傳圖片的onChange只觸發了一次。

  解決方法:在onChange中始終setFileList,保證所有狀態同步到 Upload 內

 const handleChange = ({ file, fileList }: any) => {
     //...上一段代碼
   //最外層一直設置fileLsit setFileList([...fileList]); }

  這樣就可以正常上傳圖片了。

六、刪除圖片

  刪除圖片時,file的status為removed。具體代碼如下

  const handleChange = ({ file, fileList }: any) => {
   //...代碼    else if (file.status === 'removed') { if (typeof file.uid === 'number') { //請求接口,刪除已經保存過的圖片,並且成功之后triggerChange triggerChange(fileList); } else { //只是上傳到了服務器,並沒有保存,直接riggerChange triggerChange(fileList); } }
  //...代碼 }

七、預覽圖片

  1、Upload添加onPreview

<Upload
  onPreview={handlePreview}
 >
</Upload>

  2、增加Modal

<Modal
   visible={previewVisible}
   title='預覽照片'
   footer={null}
   onCancel={() => setPreviewVisible(false)}
>
   <img alt="example" style={{ width: '100%' }} src={previewImage} />
</Modal>

  3、添加previewVisible以及previewImage

const [previewVisible, setPreviewVisible] = useState<boolean>(false);
const [previewImage, setPreviewImage] = useState<string>('');

  4、添加handlePreview函數

  const handlePreview = async (file: any) => {
    setPreviewImage(file.imgUrl);    //這個圖片路徑根據自己的情況而定
    setPreviewVisible(true);
  };

  這樣,圖片的上傳,刪除,預覽功能都已經實現了。

八、完整代碼

  1、index完整代碼

import React from "react";
import { Form } from "antd";
import UploadComponent from "./UploadComponent";
export default () => {
  const [form] = Form.useForm();
  return (
    <Form
      form={form}
      initialValues={
        {
          'uploadPhoto': []
        }
      }
    >
      <Form.Item name="uploadPhoto">
        <UploadComponent />
      </Form.Item>
    </Form>
  );
};
index.tsx

  2、UploadComponent完整代碼

import React, { useState, useEffect } from "react";
import { Upload, Modal } from 'antd';
import { PlusOutlined } from "@ant-design/icons";
export default (props: any) => {
  console.log(props)
  const [fileList, setFileList] = useState<any>([])
  const [previewVisible, setPreviewVisible] = useState<boolean>(false);
  const [previewImage, setPreviewImage] = useState<string>('');
  useEffect(() => {
    if (props.value) {
      let newFileList = props.value.map((item: any) => {
        return {
          uid: item.id || item.uid,
          status: 'done',
          url: 'url' + item.imgUrl,
          imgUrl: item.imgUrl,
        }
      })
      setFileList(newFileList)
    }
  }, [props])
  const handleChange = ({ file, fileList }: any) => {
    fileList = fileList.map((file: any) => {
      if (file.response) {
        file.id = file.uid;
        file.imgUrl = file.response.data.key
      }
      return file;
    });
    if (file.status !== undefined) {
      if (file.status === 'done') {
        console.log('上傳成功')
        triggerChange(fileList);
      } else if (file.status === 'error') {
        console.log('上傳失敗')
      } else if (file.status === 'removed') {
        if (typeof file.uid === 'number') {
          //請求接口,刪除已經保存過的圖片,並且成功之后triggerChange
          triggerChange(fileList);
        } else {
          //只是上傳到了服務器,並沒有保存,直接riggerChange
          triggerChange(fileList);
        }
      }
    }
    setFileList([...fileList]);
  }
  const triggerChange = (value: any) => {
    const onChange = props.onChange;
    if (onChange) {
      onChange(value);
    }
  };
  const handlePreview = async (file: any) => {
    setPreviewImage(`url/${file.imgUrl}`);
    setPreviewVisible(true);
  };
  const uploadButton = (
    <div>
      <PlusOutlined />
      <div className="ant-upload-text">Upload</div>
    </div>
  );
  return (
    <div>
      <Upload
        listType="picture-card"
        fileList={fileList}
        onChange={handleChange}
        onPreview={handlePreview}
        action={'url'}
        headers={{
          'Duliday-Agent': '4',
          'Duliday-Agent-Version': (0x020000).toString(),
          'X-Requested-With': 'null',
          'token': 'token'
        }}
      >
        {fileList.length >= 8 ? null : uploadButton}
      </Upload>
      <Modal
        visible={previewVisible}
        title='預覽照片'
        footer={null}
        onCancel={() => setPreviewVisible(false)}
      >
        <img alt="example" style={{ width: '100%' }} src={previewImage} />
      </Modal>
    </div>
  );
};
UploadComponent.tsx

 

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM