Ant Design在处理业务表单中的一些实践
创始人
2024-05-11 16:42:06
0

文章目录

    • 前言
    • 表单处理实践
      • Modal 清空旧数据
      • 使用Form.create和getFieldDecorator对Form进行包装
      • 表单控件是switch
      • 自定义表单控件
      • Table列表
      • Select
      • showSearch 用于在选择框中显示搜索框
      • 其他需要注意的组件
        • Tabs
    • 其它

前言

目前,很多中小企业前端实现采用了react+antd技术栈。在传统业务中,大部分后台的表单和列表模式类似,通过antd组件快速搭建,可以节约时间成本。本文是实际场景中的一些实践记录,供大家参考。

表单处理实践

Modal 清空旧数据

组件有标准的 React 生命周期,关闭后状态不会自动清空。 如果希望每次打开都是新内容,需要自行手动清空旧的状态。或者打开时给 Modal 设置一个全新的 key, React 会渲染出一个全新的对话框。

第一种清空方式:显示弹窗时设置一个新的key

 componentWillReceiveProps(nextprops){//打开时设置一个新keyif(nextprops.visible)this.setState({newKey:!this.state.newKey})}this.state.newKey} visible={this.props.visible} />

第二种清空方式:关闭弹窗后,清空弹窗数据,弹窗内是表单时重置表单。

afterClose = () => {// 隐藏动画完成后重置内容this.props.form.resetFields();}this.afterClose} visible={this.props.visible} />

使用Form.create和getFieldDecorator对Form进行包装

经过包装的Form具备以下特点:

使用 Form.create 处理后的表单具有自动收集数据并校验的功能;
不再需要用 onChange 来做同步,但还是可以继续监听 onChange 等事件;
不能用控件的 value或defaultValue 等属性来设置表单域的值,默认值可以用 getFieldDecorator 里的 initialValue;
不需要用 setState,可以使用 this.props.form.setFieldsValue 来动态改变表单值,使用 this.props.form.getFieldsValue来获取表单值。
包装一个表单包括三个步骤:
第一步:

class CustomizedForm extends React.Component {}CustomizedForm = Form.create({})(CustomizedForm);

第二步:使用getFieldDecorator装饰对应的field

const FormItem = Form.Item;
const formItemLayout = {labelCol: { span: 5 },wrapperCol: { span: 12 }
};
this.submit}>...formItemLayout} label={'名称'}>{getFieldDecorator('fieldName', {//rules是表单的校验规则rules: [{ required: true, message: '请填写表单字段!' }],initialValue:'初始值'})()}

第三步:submit时添加校验逻辑和后处理

submit = (e)=> {//这里去掉默认行为,可以避免用户操作回车时提交表单e.preventDefault();//校验表单的值this.props.form.validateFields((err, values) => {if (!err) {//后处理操作}}
}

表单控件是switch

switch开关的值参数名是checked而不是value,使用时有两种方式:
第一种:引入团队封装后的switch控件

tnpm install @ali/uniform-react-components --save
import Switch from ‘@ali/uniform-react-components/lib/Switch/index’;
第二种: 使用valuePropName

{getFieldDecorator(‘switch’, { valuePropName: ‘checked’ })( )}

自定义表单控件

自定义表单控件的需求场景很多,为了能够支持 antd Form 的 getFieldDecorator 包装,从而使组件能直接用于 Form 中,需要遵守以下规则:

提供受控属性 value 或其它与 valuePropName 的值同名的属性。
提供 onChange 事件或 trigger 的值同名的事件。
不能是函数式组件。
大CMS业务中用到的自定义表单控件有很多,例如UploadImg,TreeSelect,BizTypeSelect等等,具体可以参考youku-manager和youku-scg等工程里面的实践。

Table列表

第一步:定义columns 即列表中列的描述

columns = [{title: 'ID',dataIndex: 'id',key: 'id'}, {title: '内容数量',key: 'amount',//render用于生成复杂数据的渲染函数,参数分别为当前行的值,当前行数据render: (text,record) => ()=>this.relationTagPopup(record)}>查看,},{title: '操作',key: 'action',//删除,下线等post操作使用PopConfirm进行二次确认render: (item) => (
() => this.editTag(item)}>编辑()=>this.deleteTag(item)}>删除
)}];

第二步:定义Table
rowKey属性是表格行 key 的取值,这里取的是column中的id字段,保证key值不重复
loading表示页面是否加载中,在翻页和查询时添加load效果,可以优化体验
dataSource 数据数组

this.columns} loading={state.loading} dataSource={state.tagList} pagination={{ pageSize:10, total: state.total, current: state.pageNo, }} onChange={this.handlePagination} rowKey="id" />

第三步:更新dataSource数据源

this.setState({loading:true})
IO.getTagRepertoryList(data).then(response => {if(response.success){const data = response.data;const tagList = data.itemList;const total = data.totalSize;const pageNo =  data.pageNo;const loading = false;this.setState({tagList,pageNo,total,loading});}else{Message.warning(response.message)this.setState({tagList:[],total:0,pageNo:1,loading:false});}}).catch(err => {console.error(err);this.setState({loading:false,tagList:[],total:0,pageNo:1,});Message.error('查询异常,无结果');});

Select

cms后台的业务有很多选择选择下拉需求,下面两个业务常见的select为例,解释几个比较重要的配置

多值远程搜索
screenshot.png

screenshot.png

render() { 
//fetching 查询状态,用于在接口数据返回前显示loading效果 
const { fetching, personList } = this.state; 
// Option的name属性对应的是optionLabelProp设置的值 
const options = personList.map((d,index)=> ) 
return ( 
)

optionLabelProp和labelInValue配合,默认情况下 onChange 里只能拿到 value,如果需要拿到选中的节点文本 label,可以使用 labelInValue 属性,这个人物搜索组件的Option的children是ReactNode,所以我们需要通过optionLabelProp拿到需要的文本,回显在input框中,同时给后端传递所需要的map结构。

filterOption是否根据输入项进行筛选,如果这个select的option是通过用户输入关键字请求接口渲染的,那么需要设置成false,否则可以通过特定函数设定内部筛选规则,具体的使用方法在第二个例子中具体说明。

单值内部搜索
screenshot.png


showSearch 用于在选择框中显示搜索框

filterOption 在这里定义内部搜索逻辑,默认是通过option的value进行匹配,这里为了能既能够通过id也能够通过name进行搜索,通过这个函数进行了特殊设置。

使用Fetch进行接口调用

import {fetchGet, fetchPost, fetchJsonp} from '@ali/uniform-react-components/lib/UniFetch/index';
//大cms后台的post请求需要增加token校验 
const _tb_token_ = window._tb_token_;
const params = {//fetch 请求默认是不带 cookie 的credentials: 'include',//是否允许跨域//mode: "no-cors",headers: {//服务端通过识别X-Requested-With来判定发送的fetch请求是ajax请求,数据统一封装成Json返回"X-Requested-With":"XMLHttpRequest"},
}
class IO {/** * get 请求例子 */static fetchGetSample(data) {return fetchGet('/video/v5video/item/search.htm?', data,params);}/** * post 请求例子 */static fetchPostSample(data) {data._tb_token_ = _tb_token_;return fetchPost('/video/v5video/item/add.htm', data,params);}/** * jsonp 请求例子 */static fetchJsonpSample(tags) {return fetchJsonp('/common/jsonp/getTagName.htm?', {tags: tags},params);}
}const data = {key1:value1,key2:value2}
IO.fetchPostSample({data})
.then(response=>{})
.catch(err=>{})

其他需要注意的组件

Tabs

注意如果两个tab有数据耦合,需要在切换时有针对性的刷新,比如将标签页面和标签维度放一个tabs中,如果在标签维度中添加了数据,那么切换回标签页面时,标签维度的select选项必须同步,最直接的做法就是刷新页面。
Button htmlType='submit’最常用
InputNumber 利用formatter和parser可以限制InputNumber的输入格式,比如限制用户只能输入一位小数
Spin 模拟loading状态

其它

使用diamond进行前后端分离和环境区分
目前采用diamond进行页面级别的前后端分离,工作流为:

  1. 后端提供接口和预埋数据,后台发布与前端发布隔离,这里的预埋数据前端可以通过window.paramName的全局方式获取;
  2. 后端提供日常,预发和线上三个环境的diamond地址,diamond中加入用于前端react渲染;
  3. 前端git发版本,手动在三个diamond环境内添加css和js资源,更新版本号;
  4. 由于不同的子后台域名不同,使用其他子后台接口时需要利用diamond区分接口环境,例如在优酷选品后台中要使用cms后台节目搜索接口,
    在日常的diamond中设置
    window.PROGRAM_SEARCH_URL = ‘//haibao.alibaba.net/youku/api/filter/show.json’;
    在预发和线上则改成
    window.PROGRAM_SEARCH_URL = ‘//haibao.alibaba.com/youku/api/filter/show.json’;前端通过window.PROGRAM_SEARCH_URL获得真实的接口地址。
  5. 存在的问题:diamond方案虽然可以使版本升级通过推送提高效率,但会产生前后端无法同时生效、回滚异常等副作用,需要进一步思考。

相关内容

热门资讯

安卓系统的手机优缺点,全面解析... 你有没有发现,现在市面上手机种类繁多,让人挑花了眼?其中,安卓系统的手机可是占据了半壁江山呢!今天,...
平板有没有安卓系统,安卓系统引... 你有没有想过,平板电脑到底有没有安卓系统呢?这个问题听起来可能有点奇怪,但确实很多人在选购平板时都会...
安卓手机双系统好用不,安卓手机... 你有没有想过,你的安卓手机是不是也能像多面手一样,既能驾驭工作,又能享受娱乐呢?没错,说的就是那个神...
安卓系统怎么登录国际服,一键操... 你有没有想过,为什么有时候你的安卓手机上会出现那些国际服的游戏呢?是不是好奇怎么登录这些神秘的国外服...
安卓系统的时间天气没了,天气功... 最近你的安卓手机是不是也遇到了一个让人头疼的小问题?那就是——时间天气不见了!没错,就是那个曾经陪伴...
安卓好用的拍照系统,捕捉美好瞬... 你有没有发现,现在手机拍照功能越来越强大了?尤其是安卓手机,拍照系统简直让人爱不释手!今天,就让我带...
软件如何兼容安卓8系统,助您软... 你有没有发现,随着科技的飞速发展,手机软件更新换代的速度也是越来越快呢!这不,安卓8系统已经悄然来临...
安卓通用版系统下载,畅享智能生... 你有没有发现,最近手机界又掀起了一股热潮?没错,就是安卓通用版系统下载!这可是个让无数安卓用户兴奋不...
安卓无线点餐系统ph,PH技术... 你有没有想过,点餐也能变得如此轻松愉快?没错,就是那个我们每天都要面对的吃饭问题,现在有了安卓无线点...
安卓门禁系统怎么样,便捷通行新... 你有没有想过,每天回家时,只需轻轻一刷,门就自动打开了?这就是安卓门禁系统的魅力所在!今天,就让我带...
在电脑上模拟安卓系统,探索虚拟... 你有没有想过,在电脑上也能体验安卓系统的乐趣呢?没错,就是那种随时随地都能玩手机的感觉,现在也能在电...
飞机送餐安卓系统,空中美食新体... 你有没有想过,飞机上的美食是如何送到你手中的?是不是觉得这背后有着神秘的力量?其实,这一切都离不开高...
findx耍原生安卓系统,深度... 亲爱的读者们,你是否厌倦了那些花里胡哨的定制系统,渴望回到那个纯净的安卓世界?今天,我要带你一起探索...
一加系统属于安卓系统吗,引领智... 你有没有想过,手机里的那个神奇的“一加系统”到底是不是安卓系统的一员呢?这可是个让人好奇不已的问题哦...
小米2刷安卓系统吗,探索安卓系... 亲爱的读者,你是否曾经对小米2这款手机刷安卓系统的事情感到好奇呢?今天,就让我带你一探究竟,揭开小米...
安卓7.0系统线刷包,深度解析... 你有没有发现,你的安卓手机最近有点儿“蔫儿”了?别急,别急,今天就来给你揭秘如何让你的安卓手机重焕生...
白菜系统和安卓拍照,开启智能生... 你知道吗?最近我在用手机拍照的时候,发现了一个超级酷的功能,简直让我爱不释手!那就是——白菜系统和安...
安卓系统查杀病毒,全方位守护您... 手机里的安卓系统是不是有时候会突然弹出一个查杀病毒的提示?别慌,这可不是什么大问题,今天就来给你详细...
iso系统与安卓各系统哪个好,... 你有没有想过,手机操作系统就像是我们生活中的不同交通工具,各有各的特色和优势。今天,咱们就来聊聊这个...
中柏怎么换安卓系统,解锁更多可... 你有没有发现,中柏的安卓系统有时候用起来还挺不顺手的?别急,今天就来手把手教你如何给中柏手机升级安卓...