对于 React 结合 Antd 的 Upload 组件实现图片上传

一、 React 结合 Antd 实现图片上传
  1. 引入所需相关的组件和文件,代码如下所示:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Upload, Icon, Modal, message } from 'antd'
import { reqDeleteImg } from '../../api'
import { BASE_IMG_URL } from '../../utils/constants'
  1. 创建 PicturesWall 图片上传组件,定义初始化的 statepreviewVisible 为标识是否显示大图预览 Modal,默认为 falsepreviewImage 为大图的 url,默认为空。fileList 为所有已上传图片文件对象的数组,默认为空数组,代码如下所示:
state = {
    previewVisible: false, 
    previewImage: '', 
    fileList: [], 
  }
  1. PicturesWall 组件中创建三个方法,getImgs 是获取所有已上传图片文件名的数组,handleCancel 是隐藏 ModalhandlePreview 是预览大图图片。对于获取上传图片数组,可以直接遍历 state 中的 fileList 得到。对于隐藏 Modal,通过 setState 设置 previewVisiblefalse 就可以。对于预览大图图片,通过 setState 设置 previewImage,显示指定 file 对应的大图,同时设置 previewVisibletrue 就可以,代码如下所示:
  getImgs = () => {
    return this.state.fileList.map(file => file.name)
  }

  handleCancel = () => this.setState({ previewVisible: false })

  handlePreview = file => {
    this.setState({
      previewImage: file.url || file.thumbUrl,
      previewVisible: true,
    })
  }
  1. handleChange 方法中,去实现图片上传的功能。file 是当前操作的图片文件(上传/删除),fileList 是所有已上传图片文件对象的数组。判断当前 filestatus,如果是 done,说明当前操作是上传图片。通过 file.response 获取 result。如果 result.status 为 0,说明图片上传成功,从结果中结构获取 nameurl,反之则图片上传失败。如果当前 filestatusremoved,说明当前操作是删除图片,调用删除图片的接口。如果 result.status 为 0,说明删除图片成功,反之则删除失败。最后,通过 setState 设置 fileList,在操作(上传/删除)过程中更新 fileList 状态,代码如下所示:
  handleChange = async ({ file, fileList }) => {
    if (file.status === 'done') { 
      // {status: 0, data: {name: 'xxx.jpg', url: '图片地址'}}
      const result = file.response
      if (result.status === 0) {
        message.success('上传图片成功')
        const { name, url } = result.data
        file = fileList[fileList.length - 1]
        file.name = name
        file.url = url
      } else {
        message.error('上传图片失败')
      }
    } else if (file.status === 'removed') { 
      const result = await reqDeleteImg(file.name)
      if (result.status === 0) {
        message.success('删除图片成功!')
      } else {
        message.error('删除图片失败!')
      }
    }
    this.setState({ fileList })
  }
  1. render 中,通过 this.state 解构获取 previewVisiblepreviewImagefileList,使用 Upload 组件实现图片上传和删除的显示。action 是上传图片的接口地址,accept 是只接收图片格式,name 是请求参数名,listType 是卡片样式,fileList 是所有已上传图片文件对象的数组,onPreview 是点击文件链接或预览图标时的回调,onChange 是上传文件改变时的状态,代码如下所示:
render() {
    const { previewVisible, previewImage, fileList } = this.state
    const uploadButton = (
      <div>
        <Icon type="plus" />
        <div>Upload</div>
      </div>
    );
    return (
      <div className="clearfix">
        <Upload
          action="/manage/img/upload" 
          accept="image/*" 
          name="image" 
          listType="picture-card" 
          fileList={fileList} 
          onPreview={this.handlePreview}
          onChange={this.handleChange}
        >
          {fileList.length >= 8 ? null : uploadButton}
        </Upload>
        <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
          <img alt="example" style={{ width: '100%' }} src={previewImage} />
        </Modal>
      </div>
    )
  1. addUpdate 组件中去使用图片上传组件 PicturesWall。在这里就会涉及到组件传值的问题。子组件调用父组件的方法是将父组件的方法以函数属性的形式传递给子组件, 子组件就可以调用。父组件调用子组件的方法是在父组件中通过 ref 得到子组件标签对象(也就是组件对象), 调用其方法。所以,我们就可以通过 ref 去实现组件传值。首先,创建 ref 容器,在 constructor 中,通过 React.createRef() 进行创建用来保存 ref 标识的标签对象的容器,代码如下所示:
constructor (props) {
    super(props)
    this.pw = React.createRef()
    this.editor = React.createRef()
  }
  1. 然后,在 addUpdate 组件中,将 ref 容器交给需要获取的标签元素,进行使用,代码如下所示:
<Item label="商品图片">
    <PicturesWall ref={this.pw} imgs={imgs}></PicturesWall>
</Item>
  1. 最后,通过 ref 容器读取标签元素。在表单提交的时候,去进行读取,代码如下所示:
const imgs = this.pw.current.getImgs()
  1. PicturesWall 组件中,通过 prop-types 中的 PropTypes 进行检测由父组件传入的 imgs 的数据,由 PropTypes.array 判断传入的 imgs 必须为数组。在 constructor 中,通过 this.props 获取传入的 imgs 属性。判断只有当 imgs 存在 并且 imgs.length 要大于 0,将 imgs 进行 map 遍历得到 fileListuid 是每个 file 都有自己唯一的 idname 是图片文件名,status 是图片状态: done 是已上传, uploading 是正在上传中, removed 是已删除。最后,通过 setState 初始化状态,previewVisiblefalsepreviewImage 为空,fileList 为图片上传数组,代码如下所示:
static propTypes = {
    imgs: PropTypes.array
 }
 
 constructor (props) {
    super(props)
    let fileList = []
    const { imgs } = this.props
    if (imgs && imgs.length>0) {
      fileList = imgs.map((img, index) => ({
        uid: -index, 
        name: img, 
        status: 'done', 
        url: BASE_IMG_URL + img
      }))
    }
    this.setState({
      previewVisible: false, 
      previewImage: '', 
      fileList 
    })
  }
二、React 结合 Antd 实现图片上传的实现
  1. React 结合 Antd 实现图片上传的实现,完整代码如下所示:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Upload, Icon, Modal, message } from 'antd'
import { reqDeleteImg } from '../../api'
import { BASE_IMG_URL } from '../../utils/constants'

export default class PicturesWall extends Component {
  
  static propTypes = {
    imgs: PropTypes.array
  }

  state = {
    previewVisible: false, 
    previewImage: '', 
    fileList: [], 
  }

  constructor (props) {
    super(props)
    let fileList = []
    const { imgs } = this.props
    if (imgs && imgs.length>0) {
      fileList = imgs.map((img, index) => ({
        uid: -index, 
        name: img, 
        status: 'done', 
        url: BASE_IMG_URL + img
      }))
    }
    this.setState({
      previewVisible: false, 
      previewImage: '', 
      fileList 
    })
  }

  getImgs = () => {
    return this.state.fileList.map(file => file.name)
  }

  handleCancel = () => this.setState({ previewVisible: false })

  handlePreview = file => {
    this.setState({
      previewImage: file.url || file.thumbUrl,
      previewVisible: true,
    })
  }

  handleChange = async ({ file, fileList }) => {

    if (file.status === 'done') { 
      // {status: 0, data: {name: 'xxx.jpg', url: '图片地址'}}
      const result = file.response
      if (result.status === 0) {
        message.success('上传图片成功')
        const { name, url } = result.data
        file = fileList[fileList.length - 1]
        file.name = name
        file.url = url
      } else {
        message.error('上传图片失败')
      }
    } else if (file.status === 'removed') { 
      const result = await reqDeleteImg(file.name)
      if (result.status === 0) {
        message.success('删除图片成功!')
      } else {
        message.error('删除图片失败!')
      }
    }
    this.setState({ fileList })
  }

  render() {
    const { previewVisible, previewImage, fileList } = this.state
    const uploadButton = (
      <div>
        <Icon type="plus" />
        <div>Upload</div>
      </div>
    );
    return (
      <div className="clearfix">
        <Upload
          action="/manage/img/upload" 
          accept="image/*" 
          name="image" 
          listType="picture-card" 
          fileList={fileList} 
          onPreview={this.handlePreview}
          onChange={this.handleChange}
        >
          {fileList.length >= 8 ? null : uploadButton}
        </Upload>
        <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
          <img alt="example" style={{ width: '100%' }} src={previewImage} />
        </Modal>
      </div>
    );
  }
}

你可能感兴趣的:(React,React,Antd,Upload,组件,实现图片上传)