AntD的 upload组件的使用
This commit is contained in:
		
							parent
							
								
									4837e80f54
								
							
						
					
					
						commit
						03e8312f52
					
				
							
								
								
									
										590
									
								
								13-React基础/09-AntD框架的upload组件上传图片时遇到的一些坑.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										590
									
								
								13-React基础/09-AntD框架的upload组件上传图片时遇到的一些坑.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,590 @@
 | 
			
		||||
 | 
			
		||||
## 前言
 | 
			
		||||
 | 
			
		||||
本次做后台管理系统,采用的是 AntD 框架。涉及到图片的上传,用的是AntD的 [upload](https://ant.design/components/upload-cn/) 组件。
 | 
			
		||||
 | 
			
		||||
前端做文件上传这个功能,是很有技术难度的。既然框架给我们提供好了,那就直接用呗。结果用的时候,发现 upload 组件的很多bug。
 | 
			
		||||
 | 
			
		||||
## 使用 AntD 的 upload 组件做图片的上传
 | 
			
		||||
 | 
			
		||||
因为需要上传多张图片,所以采用的是照片墙的形式。上传成功后的界面如下:
 | 
			
		||||
 | 
			
		||||
按照官方提供的实例,特此整理出项目开发中的完整写法,亲测有效。代码如下:
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
 | 
			
		||||
import { Upload, Icon, Modal, Form } from 'antd';
 | 
			
		||||
 | 
			
		||||
const FormItem = Form.Item;
 | 
			
		||||
 | 
			
		||||
class PicturesWall extends PureComponent {
 | 
			
		||||
  state = {
 | 
			
		||||
    previewVisible: false,
 | 
			
		||||
    previewImage: '',
 | 
			
		||||
    imgList: [],
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  handleChange = ({ file, fileList }) => {
 | 
			
		||||
    console.log(JSON.stringify(file)); // file 是当前正在上传的 单个 img
 | 
			
		||||
    console.log(JSON.stringify(fileList)); // fileList 是已上传的全部 img 列表
 | 
			
		||||
 | 
			
		||||
    this.setState({
 | 
			
		||||
      imgList: fileList,
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  handleCancel = () => this.setState({ previewVisible: false });
 | 
			
		||||
 | 
			
		||||
  handlePreview = file => {
 | 
			
		||||
    this.setState({
 | 
			
		||||
      previewImage: file.url || file.thumbUrl,
 | 
			
		||||
      previewVisible: true,
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // 参考链接:https://www.jianshu.com/p/f356f050b3c9
 | 
			
		||||
  handleBeforeUpload = file => {
 | 
			
		||||
    //限制图片 格式、size、分辨率
 | 
			
		||||
    const isJPG = file.type === 'image/jpeg';
 | 
			
		||||
    const isJPEG = file.type === 'image/jpeg';
 | 
			
		||||
    const isGIF = file.type === 'image/gif';
 | 
			
		||||
    const isPNG = file.type === 'image/png';
 | 
			
		||||
    if (!(isJPG || isJPEG || isGIF || isPNG)) {
 | 
			
		||||
      Modal.error({
 | 
			
		||||
        title: '只能上传JPG 、JPEG 、GIF、 PNG格式的图片~',
 | 
			
		||||
      });
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const isLt2M = file.size / 1024 / 1024 < 2;
 | 
			
		||||
    if (!isLt2M) {
 | 
			
		||||
      Modal.error({
 | 
			
		||||
        title: '超过2M限制 不允许上传~',
 | 
			
		||||
      });
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    return (isJPG || isJPEG || isGIF || isPNG) && isLt2M && this.checkImageWH(file);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  //返回一个 promise:检测通过则返回resolve;失败则返回reject,并阻止图片上传
 | 
			
		||||
  checkImageWH(file) {
 | 
			
		||||
    let self = this;
 | 
			
		||||
    return new Promise(function(resolve, reject) {
 | 
			
		||||
      let filereader = new FileReader();
 | 
			
		||||
      filereader.onload = e => {
 | 
			
		||||
        let src = e.target.result;
 | 
			
		||||
        const image = new Image();
 | 
			
		||||
        image.onload = function() {
 | 
			
		||||
          // 获取图片的宽高,并存放到file对象中
 | 
			
		||||
          console.log('file width :' + this.width);
 | 
			
		||||
          console.log('file height :' + this.height);
 | 
			
		||||
          file.width = this.width;
 | 
			
		||||
          file.height = this.height;
 | 
			
		||||
          resolve();
 | 
			
		||||
        };
 | 
			
		||||
        image.onerror = reject;
 | 
			
		||||
        image.src = src;
 | 
			
		||||
      };
 | 
			
		||||
      filereader.readAsDataURL(file);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleSubmit = e => {
 | 
			
		||||
    const { dispatch, form } = this.props;
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    form.validateFieldsAndScroll((err, values) => {// values 是form表单里的参数
 | 
			
		||||
      // 点击按钮后,将表单提交给后台
 | 
			
		||||
      dispatch({
 | 
			
		||||
        type: 'mymodel/submitFormData',
 | 
			
		||||
        payload: values,
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  render() {
 | 
			
		||||
    const { previewVisible, previewImage, imgList } = this.state; //  从 state 中拿数据
 | 
			
		||||
    const uploadButton = (
 | 
			
		||||
      <div>
 | 
			
		||||
        <Icon type="plus" />
 | 
			
		||||
        <div className="ant-upload-text">Upload</div>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
    return (
 | 
			
		||||
      <div className="clearfix">
 | 
			
		||||
        <Form onSubmit={this.handleSubmit} hideRequiredMark style={{ marginTop: 8 }}>
 | 
			
		||||
          <FormItem label="工厂图片" {...formItemLayout}>
 | 
			
		||||
            {getFieldDecorator('myImg')(
 | 
			
		||||
              <Upload
 | 
			
		||||
                action="//jsonplaceholder.typicode.com/posts/" // 这个是接口请求
 | 
			
		||||
                data={file => ({ // data里存放的是接口的请求参数
 | 
			
		||||
                  param1: myParam1,
 | 
			
		||||
                  param2: myParam2,
 | 
			
		||||
                  photoCotent: file, // file 是当前正在上传的图片
 | 
			
		||||
                  photoWidth: file.height, // 通过  handleBeforeUpload 获取 图片的宽高
 | 
			
		||||
                  photoHeight: file.width,
 | 
			
		||||
                })}
 | 
			
		||||
                listType="picture-card"
 | 
			
		||||
                fileList={this.state.imgList}
 | 
			
		||||
                onPreview={this.handlePreview} // 点击图片缩略图,进行预览
 | 
			
		||||
                beforeUpload={this.handleBeforeUpload} // 上传之前,对图片的格式做校验,并获取图片的宽高
 | 
			
		||||
                onChange={this.handleChange} // 每次上传图片时,都会触发这个方法
 | 
			
		||||
              >
 | 
			
		||||
                {this.state.imgList.length >= 9 ? null : uploadButton}
 | 
			
		||||
              </Upload>
 | 
			
		||||
            )}
 | 
			
		||||
          </FormItem>
 | 
			
		||||
        </Form>
 | 
			
		||||
        <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
 | 
			
		||||
          <img alt="example" style={{ width: '100%' }} src={previewImage} />
 | 
			
		||||
        </Modal>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default PicturesWall;
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 上传后,点击图片预览,浏览器卡死的问题
 | 
			
		||||
 | 
			
		||||
依据上方的代码,通过 Antd 的 upload 组件将图片上传成功后,点击图片的缩略图,理应可以在当前页面弹出  Modal,预览图片。但实际的结果是,浏览器一定会卡死。
 | 
			
		||||
 | 
			
		||||
定位问题发现,原因竟然是:图片上传成功后, upload 会将其转为 base64编码。base64这个字符串太大了,点击图片预览的时候,浏览器在解析一大串字符串,然后就卡死了。详细过程描述如下。
 | 
			
		||||
 | 
			
		||||
上方代码中,我们可以把 handleChange(file, fileList)方法中的 `file`、以及 `fileList`打印出来看看。 `file`指的是当前正在上传的 单个 img,`fileList`是已上传的全部 img 列表。 当我上传完 两张图片后, 打印结果如下:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
file的打印的结果如下:
 | 
			
		||||
 | 
			
		||||
```json
 | 
			
		||||
    {
 | 
			
		||||
        "uid": "rc-upload-1551084269812-5",
 | 
			
		||||
        "width": 600,
 | 
			
		||||
        "height": 354,
 | 
			
		||||
        "lastModified": 1546701318000,
 | 
			
		||||
        "lastModifiedDate": "2019-01-05T15:15:18.000Z",
 | 
			
		||||
        "name": "e30e7b9680634b2c888c8bb513cc595d.jpg",
 | 
			
		||||
        "size": 31731,
 | 
			
		||||
        "type": "image/jpeg",
 | 
			
		||||
        "percent": 100,
 | 
			
		||||
        "originFileObj": {
 | 
			
		||||
            "uid": "rc-upload-1551084269812-5",
 | 
			
		||||
            "width": 600,
 | 
			
		||||
            "height": 354
 | 
			
		||||
        },
 | 
			
		||||
        "status": "done",
 | 
			
		||||
        "thumbUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAHQ9qKKlbimcXrIH9o2vH/AC2T+ddPj98v+9RRWsuhnHdk0ar9qb5R0Pb6VPB/qh9aKKiRr0Irnt/vUDr+NFFJCRqWxJik5Pb+dLJ938aKK06mYSdKKKKBH//Z",
 | 
			
		||||
        "response": {
 | 
			
		||||
            "retCode": 0,
 | 
			
		||||
            "imgUrl": "http://qianguyihao.com/opfewfwj098902kpkpkkj976fe.jpg",
 | 
			
		||||
            "photoid": 271850
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fileList 的打印结果:
 | 
			
		||||
 | 
			
		||||
```json
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "uid": "rc-upload-1551084269812-3",
 | 
			
		||||
        "width": 1000,
 | 
			
		||||
        "height": 667,
 | 
			
		||||
        "lastModified": 1501414799000,
 | 
			
		||||
        "lastModifiedDate": "2017-07-30T11:39:59.000Z",
 | 
			
		||||
        "name": "29381f30e924b89914e91b33.jpg",
 | 
			
		||||
        "size": 135204,
 | 
			
		||||
        "type": "image/jpeg",
 | 
			
		||||
        "percent": 100,
 | 
			
		||||
        "originFileObj": {
 | 
			
		||||
            "uid": "rc-upload-1551084269812-3",
 | 
			
		||||
            "width": 1000,
 | 
			
		||||
            "height": 667
 | 
			
		||||
        },
 | 
			
		||||
        "status": "done",
 | 
			
		||||
        "thumbUrl": "data:image/jpeg;base64,/E3ju1tlaK1fzJOnHQU3LsLV7HO6Zrk11MZJ7luT0A4FZuRagi9quvzQQ4iuEJ7ZpqTG4djDsPFl2Lg733f8C4q+YhQ8zoYfGSqoMmfwo5huLL0HjiyPDSYPvxRdC1XQvxeLrB8fvl/OnoLmL9vrdvvYS3NGFVe2YsASOh71JfQyrqV2mXLHOcccVSIYEnDyZO9XXB9KYH//Z",
 | 
			
		||||
        "response": {
 | 
			
		||||
            "retCode": 0,
 | 
			
		||||
            "msg": "success",
 | 
			
		||||
            "imgUrl": "http://qianguyihao.com/hfwpjouiurewnmbhepr689.jpg",
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "uid": "rc-upload-1551084269812-5",
 | 
			
		||||
        "width": 600,
 | 
			
		||||
        "height": 354,
 | 
			
		||||
        "lastModified": 1546701318000,
 | 
			
		||||
        "lastModifiedDate": "2019-01-05T15:15:18.000Z",
 | 
			
		||||
        "name": "e30e7b9680634b2c888c8bb513cc595d.jpg",
 | 
			
		||||
        "size": 31731,
 | 
			
		||||
        "type": "image/jpeg",
 | 
			
		||||
        "percent": 100,
 | 
			
		||||
        "originFileObj": {
 | 
			
		||||
            "uid": "rc-upload-1551084269812-5",
 | 
			
		||||
            "width": 600,
 | 
			
		||||
            "height": 354
 | 
			
		||||
        },
 | 
			
		||||
        "status": "done",
 | 
			
		||||
        "thumbUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAHQ9qKKlbimcXrIH9o2vH/AC2T+ddPj98v+9RRWsuhnHdk0ar9qb5R0Pb6VPB/qh9aKKiRr0Irnt/vUDr+NFFJCRqWxJik5Pb+dLJ938aKK06mYSdKKKKBH//Z",
 | 
			
		||||
        "response": {
 | 
			
		||||
            "retCode": 0,
 | 
			
		||||
            "imgUrl": "http://qianguyihao.com/opfewfwj098902kpkpkkj976fe.jpg",
 | 
			
		||||
            "photoid": 271850
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
上方的json数据中,需要做几点解释:
 | 
			
		||||
 | 
			
		||||
(1)`response` 字段里面的数据,就是请求接口后,后台返回给前端的数据,里面包含了图片的url链接。
 | 
			
		||||
 | 
			
		||||
(2)`status` 字段里存放的是图片上传的实时状态。
 | 
			
		||||
 | 
			
		||||
(3)`thumbUrl`字段里面存放的是图片的base64编码。
 | 
			
		||||
 | 
			
		||||
这个base64编码非常非常长。当点击图片预览的时候,其实就是加载的 thumbUrl 这个字段里的资源,难怪浏览器会卡死。
 | 
			
		||||
 | 
			
		||||
**解决办法**:在 handleChange方法里,图片上传成功后,将 thumbUrl 字段里面的 base64 编码改为真实的图片url。代码实现如下:
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
  handleChange = ({ file, fileList }) => {
 | 
			
		||||
    console.log(JSON.stringify(file)); // file 是当前正在上传的 单个 img
 | 
			
		||||
    console.log(JSON.stringify(fileList)); // fileList 是已上传的全部 img 列表
 | 
			
		||||
 | 
			
		||||
    if (file && file.response && file.response.retCode == 0) {
 | 
			
		||||
      console.log('图片上传成功');
 | 
			
		||||
      fileList.forEach(item => {
 | 
			
		||||
        // 【重要】将 图片的base64替换为图片的url。 这一行一定不会能少。
 | 
			
		||||
        // 图片上传成功后,fileList数组中的 thumbUrl 中保存的是图片的base64字符串,这种情况,导致的问题是:图片上传成功后,点击图片缩略图,浏览器会会卡死。而下面这行代码,可以解决该bug。
 | 
			
		||||
        item.thumbUrl = item.response.imgUrl;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.setState({
 | 
			
		||||
      imgList: fileList,
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 新需求:编辑现有页面
 | 
			
		||||
 | 
			
		||||
上面一段的代码中,我们是在新建的页面中,从零开始上传页面。
 | 
			
		||||
 | 
			
		||||
现在有个新的需求:如何编辑现有的页面呢?也就是说说,现有的页面中,是默认有几张图片的。当我编辑这个页面时,可以对现有的图片做增删,也能增加新的图片。
 | 
			
		||||
 | 
			
		||||
我的model层代码,是用 redux 写的。实现思路如下:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
(1)PicturesWall.js:
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
 | 
			
		||||
import { Upload, Icon, Modal, Form } from 'antd';
 | 
			
		||||
 | 
			
		||||
const FormItem = Form.Item;
 | 
			
		||||
 | 
			
		||||
class PicturesWall extends PureComponent {
 | 
			
		||||
  state = {
 | 
			
		||||
    previewVisible: false,
 | 
			
		||||
    previewImage: '',
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // 页面初始化的时候,从接口拉取默认的图片数据
 | 
			
		||||
  componentDidMount() {
 | 
			
		||||
    const { dispatch } = this.props;
 | 
			
		||||
    dispatch({
 | 
			
		||||
      type: 'mymodel/getAllInfo',
 | 
			
		||||
      payload: { params: xxx },
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleChange = ({ file, fileList }) => {
 | 
			
		||||
    const { dispatch } = this.props;
 | 
			
		||||
    if (file && file.response && file.response.retCode == 0) {
 | 
			
		||||
      console.log('图片上传成功');
 | 
			
		||||
      fileList.forEach(item => {
 | 
			
		||||
        // 【重要】将 图片的base64替换为图片的url。 这一行一定不会能少。
 | 
			
		||||
        // 图片上传成功后,fileList数组中的 thumbUrl 中保存的是图片的base64字符串,这种情况,导致的问题是:图片上传成功后,点击图片缩略图,浏览器会会卡死。而下面这行代码,可以解决该bug。
 | 
			
		||||
        item.thumbUrl = item.response.imgUrl;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dispatch({
 | 
			
		||||
      type: 'mymodel/setImgList',
 | 
			
		||||
      payload: fileList,
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  handleCancel = () => this.setState({ previewVisible: false });
 | 
			
		||||
 | 
			
		||||
  handlePreview = file => {
 | 
			
		||||
    this.setState({
 | 
			
		||||
      previewImage: file.url || file.thumbUrl,
 | 
			
		||||
      previewVisible: true,
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // 参考链接:https://www.jianshu.com/p/f356f050b3c9
 | 
			
		||||
  handleBeforeUpload = file => {
 | 
			
		||||
    //限制图片 格式、size、分辨率
 | 
			
		||||
    const isJPG = file.type === 'image/jpeg';
 | 
			
		||||
    const isJPEG = file.type === 'image/jpeg';
 | 
			
		||||
    const isGIF = file.type === 'image/gif';
 | 
			
		||||
    const isPNG = file.type === 'image/png';
 | 
			
		||||
    if (!(isJPG || isJPEG || isGIF || isPNG)) {
 | 
			
		||||
      Modal.error({
 | 
			
		||||
        title: '只能上传JPG 、JPEG 、GIF、 PNG格式的图片~',
 | 
			
		||||
      });
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const isLt2M = file.size / 1024 / 1024 < 2;
 | 
			
		||||
    if (!isLt2M) {
 | 
			
		||||
      Modal.error({
 | 
			
		||||
        title: '超过2M限制 不允许上传~',
 | 
			
		||||
      });
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    return (isJPG || isJPEG || isGIF || isPNG) && isLt2M && this.checkImageWH(file);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  //返回一个 promise:检测通过则返回resolve;失败则返回reject,并阻止图片上传
 | 
			
		||||
  checkImageWH(file) {
 | 
			
		||||
    let self = this;
 | 
			
		||||
    return new Promise(function(resolve, reject) {
 | 
			
		||||
      let filereader = new FileReader();
 | 
			
		||||
      filereader.onload = e => {
 | 
			
		||||
        let src = e.target.result;
 | 
			
		||||
        const image = new Image();
 | 
			
		||||
        image.onload = function() {
 | 
			
		||||
          // 获取图片的宽高,并存放到file对象中
 | 
			
		||||
          console.log('file width :' + this.width);
 | 
			
		||||
          console.log('file height :' + this.height);
 | 
			
		||||
          file.width = this.width;
 | 
			
		||||
          file.height = this.height;
 | 
			
		||||
          resolve();
 | 
			
		||||
        };
 | 
			
		||||
        image.onerror = reject;
 | 
			
		||||
        image.src = src;
 | 
			
		||||
      };
 | 
			
		||||
      filereader.readAsDataURL(file);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleSubmit = e => {
 | 
			
		||||
    const { dispatch, form } = this.props;
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    form.validateFieldsAndScroll((err, values) => {
 | 
			
		||||
      // values 是form表单里的参数
 | 
			
		||||
      // 点击按钮后,将表单提交给后台
 | 
			
		||||
      dispatch({
 | 
			
		||||
        type: 'mymodel/submitFormData',
 | 
			
		||||
        payload: values,
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  render() {
 | 
			
		||||
    const { previewVisible, previewImage } = this.state; //  从 state 中拿数据
 | 
			
		||||
 | 
			
		||||
    const {
 | 
			
		||||
      mymodel: { imgList }, // 从props中拿到的图片数据
 | 
			
		||||
    } = this.props;
 | 
			
		||||
 | 
			
		||||
    const uploadButton = (
 | 
			
		||||
      <div>
 | 
			
		||||
        <Icon type="plus" />
 | 
			
		||||
        <div className="ant-upload-text">Upload</div>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
    return (
 | 
			
		||||
      <div className="clearfix">
 | 
			
		||||
        <Form onSubmit={this.handleSubmit} hideRequiredMark style={{ marginTop: 8 }}>
 | 
			
		||||
          <FormItem label="工厂图片" {...formItemLayout}>
 | 
			
		||||
            {getFieldDecorator('myImg')(
 | 
			
		||||
              <Upload
 | 
			
		||||
                action="//jsonplaceholder.typicode.com/posts/" // 这个是接口请求
 | 
			
		||||
                data={file => ({
 | 
			
		||||
                  // data里存放的是接口的请求参数
 | 
			
		||||
                  param1: myParam1,
 | 
			
		||||
                  param2: myParam2,
 | 
			
		||||
                  photoCotent: file, // file 是当前正在上传的图片
 | 
			
		||||
                  photoWidth: file.height, // 通过  handleBeforeUpload 获取 图片的宽高
 | 
			
		||||
                  photoHeight: file.width,
 | 
			
		||||
                })}
 | 
			
		||||
                listType="picture-card"
 | 
			
		||||
                fileList={imgList}  // 改为从 props 里拿图片数据,而不是从 state
 | 
			
		||||
                onPreview={this.handlePreview} // 点击图片缩略图,进行预览
 | 
			
		||||
                beforeUpload={this.handleBeforeUpload} // 上传之前,对图片的格式做校验,并获取图片的宽高
 | 
			
		||||
                onChange={this.handleChange} // 每次上传图片时,都会触发这个方法
 | 
			
		||||
              >
 | 
			
		||||
                {this.state.imgList.length >= 9 ? null : uploadButton}
 | 
			
		||||
              </Upload>
 | 
			
		||||
            )}
 | 
			
		||||
          </FormItem>
 | 
			
		||||
        </Form>
 | 
			
		||||
        <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
 | 
			
		||||
          <img alt="example" style={{ width: '100%' }} src={previewImage} />
 | 
			
		||||
        </Modal>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default PicturesWall;
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
(2)mymodel.js:
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
 | 
			
		||||
import { routerRedux } from 'dva/router';
 | 
			
		||||
import { message, Modal } from 'antd';
 | 
			
		||||
import {
 | 
			
		||||
  getTuanList,
 | 
			
		||||
  getAllFactory,
 | 
			
		||||
  getAllFactGoods,
 | 
			
		||||
  createFactShop,
 | 
			
		||||
  updateFactShop,
 | 
			
		||||
  deleteFactShop,
 | 
			
		||||
  updateFactGoodsStatus,
 | 
			
		||||
  queryShopDetail,
 | 
			
		||||
  createFactGoods,
 | 
			
		||||
} from '../services/api';
 | 
			
		||||
import { trim, getCookie } from '../utils/utils';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  namespace: 'factory',
 | 
			
		||||
 | 
			
		||||
  state: {
 | 
			
		||||
    form: {},
 | 
			
		||||
    list: [],
 | 
			
		||||
    listDetail: [],
 | 
			
		||||
    goodsList: [],
 | 
			
		||||
    goodsListDetail: [],
 | 
			
		||||
    pagination: {
 | 
			
		||||
      pageSize: 10,
 | 
			
		||||
      total: 0,
 | 
			
		||||
      current: 1,
 | 
			
		||||
    },
 | 
			
		||||
    imgList: [], //图片
 | 
			
		||||
  },
 | 
			
		||||
  subscriptions: {
 | 
			
		||||
    setup({ dispatch, history }) {
 | 
			
		||||
      history.listen(location => {
 | 
			
		||||
        if (location.pathname !== '/xx/xxx') return;
 | 
			
		||||
        if (!location.state || !location.state.xxxId) return;
 | 
			
		||||
        dispatch({
 | 
			
		||||
          type: 'fetch',
 | 
			
		||||
          payload: location.state,
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  effects: {
 | 
			
		||||
    // 接口。获取所有工厂店的列表 (步骤02)
 | 
			
		||||
    *getAllInfo({ payload }, { select, call, put }) {
 | 
			
		||||
      yield put({
 | 
			
		||||
        type: 'form',
 | 
			
		||||
        payload,
 | 
			
		||||
      });
 | 
			
		||||
      console.log('params:' + JSON.stringify(payload));
 | 
			
		||||
 | 
			
		||||
      let params = {};
 | 
			
		||||
      params = payload;
 | 
			
		||||
 | 
			
		||||
      const response = yield call(getAllFactory, params);
 | 
			
		||||
 | 
			
		||||
      console.log('smyhvae response:' + JSON.stringify(response));
 | 
			
		||||
      if (response.error) return;
 | 
			
		||||
      yield put({
 | 
			
		||||
        type: 'allInfo',
 | 
			
		||||
        payload:
 | 
			
		||||
          (response.data &&
 | 
			
		||||
            response.data.map(item => ({
 | 
			
		||||
              xx1: item.yy1,
 | 
			
		||||
              xx2: item.yy2,
 | 
			
		||||
            }))) ||
 | 
			
		||||
          [],
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // response 里包含了接口返回给前端的默认图片数据
 | 
			
		||||
      if (response && response.data && response.data[0] && response.data[0].my_jpg) {
 | 
			
		||||
        let tempImgList = response.data[0].my_jpg.split(',');
 | 
			
		||||
        let imgList = [];
 | 
			
		||||
 | 
			
		||||
        if (tempImgList.length > 0) {
 | 
			
		||||
          tempImgList.forEach(item => {
 | 
			
		||||
            imgList.push({
 | 
			
		||||
              uid: item,
 | 
			
		||||
              name: 'xxx.png',
 | 
			
		||||
              status: 'done',
 | 
			
		||||
              thumbUrl: item,
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 通过  redux的方式 将 默认图片 传给 imgList
 | 
			
		||||
        console.log('smyhvae payload imgList:' + JSON.stringify(imgList));
 | 
			
		||||
        yield put({
 | 
			
		||||
          type: 'setImgList',
 | 
			
		||||
          payload: imgList,
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    *setImgList({ payload }, { call, put }) {
 | 
			
		||||
      console.log('smyhvae model setImgList');
 | 
			
		||||
      yield put({
 | 
			
		||||
        type: 'getImgList',
 | 
			
		||||
        payload,
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  reducers: {
 | 
			
		||||
    allInfo(state, action) {
 | 
			
		||||
      return {
 | 
			
		||||
        ...state,
 | 
			
		||||
        list: action.payload,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    getImgList(state, action) {
 | 
			
		||||
      return {
 | 
			
		||||
        ...state,
 | 
			
		||||
        imgList: action.payload,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
大功告成。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
本文感谢 ld 同学的支持。
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user