React的Upload文件表单编辑回显及onCha

背景

本文介绍 antd 的 Upload 组件编辑回显的方式,以及 onChange 回调函数的使用说明。

主要知识点如下:

  1. Upload 文件上传表单,在编辑回显时,如何初始化数据?
  2. Upload 自定义 onChange 回调函数,如何传入额外的参数?
  3. React 如何通过 setState 修改数组的某一元素的值?

Upload 组件基础知识

Upload 组件提供了默认的 onChange 回调,它会回显上传文件名称,显示全部上传的文件。如果需要限制上传文件个数,使用默认回调函数且加属性 maxCount = {1} 可以达到这个效果。

但是,开发过程中通常需要自定义 onChange 事件,此时就要动态更新 Upload 的 fileList 属性,它的类型是数组,可以用 slice 实现只保留最新上传的文件信息的功能。

使用 Upload 的基本过程如下:

第一步,定义一个全局 state 变量,存储 Upload 的文件信息。

第二步,定义 onChange 事件,决定如何处理文件上传的结果。文件上传发送请求给 action 路径,上传文件到服务器后,可以返回服务器端该文件存储的路径,作为整个表单提交的信息。

onFileChange(info) {
   let fileList = [...info.fileList];
   // 1. Limit the number of uploaded files
   fileList = fileList.slice(-1);
   
   // 2. update state
   this.setState({ fileList });
   
   const response = info.fileList[0].response;
   
   // 根据响应结果,更新页面数据:限制页面只能保留一个文件,但是 onChange 会执行多次,限制提示消息只回显一次
   if(info.fileList.length ==1 && response != undefined) {
   	if( response.success) {
   		message.success("上传成功");
   		// response.data 中其他数据,看情况处理
   	} else {
   		message.error(response.message);
   	}
   }
}
复制代码

第三步,componentDidMount 方法中,初始化 fileList ,这在表单编辑回显的时候需要设置 Upload 的文件列表初始值,它的数据结构如下:

this.setState({
	fileList: [
		{
			uid: fileId,
			name: fileName,
			status: 'done',
			url: `${BASE_URL}/download?fileId=${fileId}&time=${date}`,
	}]
})
复制代码

第四步,Upload 组件渲染:

const props = {
  name: 'multipartFile',// 后端处理文件上传表单的名称
  action: `${BASE_URL}/xxx/upload`,
  onChange: this.onFileChange.bind(this)
};

<Upload showUploadList={{showRemoveIcon:false}}
   className="upload-list-inline" {...props}
   fileList={this.state.fileList} >
  <Button icon={<UploadOutlined />}>上传</Button>
</Upload>
复制代码

onChange 回调函数

Upload 的回调函数 onChange ,它有一个固定的入参,类型是 Object 对象,通过 debugger 查看,可以知道它的结构:
在这里插入图片描述

  1. file:用户上传的文件对象
  2. fileList:组件已经上传的文件列表

也就是说 Upload 组件触发 onChange 方法时会传递一个固定参数,我们如果想要传递额外的参数,需要在绑定事件的时候设置:

onChange: (info)=>this.onFileChange(info,index)
复制代码

通过匿名函数的方式指定 onChange 事件,匿名函数的方法体中调用一个自定义的方法,接收回调参数 info 和其他额外的参数 index

setState 修改数组的某个元素

React 修改 state 中某个数组对象后,不会自动反应,那么该如何修改数组对象呢?

网上没有找到答案,想到一个迂回的办法,就是先备份一下该数组对象,操作完成后再调用 setState 回设回去。

例如,列表中元素的动态新增和修改全局 state 的某个列表元素,可以这样实现:

addElement = ()=>{
   const nextNo = this.state.dataList.length+1;
   const nextStep = {
   	id: createUuid(),
   	no: nextNo,
   	name: ''
   };
   
   this.setState({
   	dataList:  this.state.dataList.concat(nextStep)
   })
}

removeElement(removeIndex,record) {
  // 移除列表数据
  this.setState({
    dataList:this.state.dataList.filter(item=> item.id !== record.id)
  })
}
复制代码

启示录

React 有个特殊的方法 bind 绑定当前对象,我了解到两种方法,一种是匿名函数的方式绑定,另一种是直接调用 bind

  1. 匿名函数:()=>this.func()
  2. 手动绑定方式:this.func.bind(this)

使用 React 后发现它能原样显示输入的数据,例如常规的 html 标签,都不会被解析成页面元素。

这样一来,就不用对前端输入数据进行转义了,Java 后端省去了编写 XSSFilter 的麻烦,还是相当方便的!