antd-img-crop,使用 Ant Design +Form +Upload 时裁切图片

1,298 阅读2分钟

背景

项目需求:图片进行剪裁后再上传
采用方案:使用Ant DesginUpload配合 antd-img-crop 实现上传前裁切图片
本文主要记录在Ant DesignForm表单中使用antd-img-crop遇到的问题及解决方法

介绍

antd-img-crop 是一个用于包装 Ant Design Upload 的组件,可实现在上传前,先对图片进行裁切,然后上传裁切后图片。

安装

pnpm add antd-img-crop
# or
yarn add antd-img-crop
# or
npm i antd-img-crop

使用

import { Upload } from 'antd';
import ImgCrop from 'antd-img-crop';

const Demo = () => (
  <ImgCrop>
    <Upload>+ Add image</Upload>
  </ImgCrop>
);

更多内容,请参考 antd-img-crop

踩坑记录

Ant DesignForm表单中使用antd-img-crop进行图片的裁剪,表单提交时,无法获取对应子节点的值

<Form.Item
  name="logo"
  label="Logo"
>
  <ImgCrop grid >
    <Upload
      action={action}
      listType="picture"
      maxCount={maxCount}
      accept=".jpg,.jpeg,.png,.gif,.tif,.bmp"
      fileList={fileList}
      onChange={onChange}
      onPreview={onPreview}
    >
      {fileList.length===0 && <label>+ 上传</label>}
    </Upload>
  </ImgCrop>
</Form.Item>

首先,我们来看下Ant Design官网的说明:

被设置了 name 属性的 Form.Item 包装的控件,表单控件会自动添加 value(或 valuePropName 指定的其他属性) onChange(或 trigger 指定的其他属性),数据同步将被 Form 接管,这会导致以下结果:

  1. 不再需要也不应该用 onChange 来做数据收集同步(你可以使用 Form 的 onValuesChange),但还是可以继续监听 onChange 事件。
  2. 你不能用控件的 value 或 defaultValue 等属性来设置表单域的值,默认值可以用 Form 里的 initialValues 来设置。注意 initialValues 不能被 setState 动态更新,你需要用 setFieldsValue 来更新。
  3. 你不应该用 setState,可以使用 form.setFieldsValue 来动态改变表单值。

这里说明一下 Form.Item(需要设置 name 属性)怎么获取子节点的值?

  • Form.Item 从子节点的 value 属性值获取,例子:input
  • Form.Item 设置了 getValuePropsvaluePropName 属性,比如设置了 valuePropName={'checked'} ,则会从子节点的 checked 属性中去获取,例子:Switch
  • 如果子节点没有 value 属性,而且从其他属性也无法获取到需要发送给后端的值,怎么办?通过 onChange 方法,或 trigger 属性指定的名称方法。由于 Form.Item 会自动向子节点传入 props :value 属性(或 valuePropName 指定的其他属性),onChange 方法(或 trigger 指定的其他名称)。所以可以在子节点调用 props.onChange(value) 方法来传递 value 值。onChange 传入的参数即该 Form.Item 会向后端发送的值。

来看下在项目中如何使用的:
在子节点调用 props.onChange(value) 方法来传递 value 值,这样在Form表单提交时,便可获取对应子节点的值

 const onChange = ({ file }) => {
    // 为了阅读方便,这里是简化后的代码
    if(file?.status === 'done'){ 
      // 在子节点调用 `props.onChange(value)` 方法来传递 `value` 值
      props.onChange(fileList) 
    }
 };