关于ant-design:记录Antd下Table属性expandIconColumnIndex设置无效的解决办法
环境:Vue2 + Antd 1.7.8版本:expandIconColumnIndex="3"设置后并未失效 解决办法: :expandIconAsCell="false":expandIconColumnIndex="1"expandIconAsCell属性在文档中并未找到,然而一起应用解决问题expandIconAsCell意思为:敞开开展按钮默认放在第一列
环境:Vue2 + Antd 1.7.8版本:expandIconColumnIndex="3"设置后并未失效 解决办法: :expandIconAsCell="false":expandIconColumnIndex="1"expandIconAsCell属性在文档中并未找到,然而一起应用解决问题expandIconAsCell意思为:敞开开展按钮默认放在第一列
应用ant-design-vue打印弹出页<div id="printContent" class="info-detail"></div> <a-button v-print="'#printContent'" type="primary" style="text-align:right">打印</a-button> 把弹出页作为子组件即可
始终想钻研一下AntDesign组件库的组件款式,碰巧最近在Umi+Ant Design+dva.js的我的项目中,须要配置theme和对组件款式批改的问题,因而间接认真的钻研,并记录为文档。本想钻研明确再发文章总结,然而碍于例子不太好复现,因而每遇到一个问题,就在此记录。 本篇文章,以<Select>组件为例进行演示和解说。 1.批改款式的办法及须要留神的问题最简略的办法就是依据Ant Design Por官网文档API中提供的属性、Style笼罩、ClassNme等办法,对组件的款式进行批改,然而这并不能齐全满足咱们的需要。比方: <Select defaultValue="lucy" style={{width: 120, backgroundColor: 'red'}}></Select>在此处对select组件的backgroudColor进行批改,然而因为Antd组件自身就有了一个属性,因而出现成果如下:这并不满足咱们的需要,因而提供下文的一系列办法。 全局批改某一种组件的款式在src/global.less文件中增加如下代码:(此处,我尝试了放到其余.less文件中后果同样能够,然而为了治理不便,倡议波及到全局批改的款式,还是在global.less文件中) #root .ant-select-selection{//在src/global.less文件中增加background: red;}出现成果如下:此时咱们发现,两个Select选择器都变成了红色背景,可是如果咱们只想扭转某一个组件背景的话,咱们该怎么办呢? 全局批改某一种组件的款式(办法2)同样,在src/global.less文件中增加如下代码: :global .ant-select-selection{background: blue;}出现成果如下:款式没有扭转的起因,见下图:因为本来的.ant-select-selection中曾经存在background-color,同时:global的优先级又没有#root高,因而不会笼罩,解决这个问题的办法就是加上! important;代码如下: :global .ant-select-selection{background: blue !important;}出现成果如下:然而这仍然解决不了,咱们只想扭转某一个组件背景的问题,上面解决办法来了! 批改某一个组件的款式(办法一)实现代码如下: .selection{:global{ .ant-select-selection{ background-color: red !important; //设置色彩 }}}import styles from '../../page.less'//.less文件为上文中定义.selection所在文件<Select defaultValue="lucy" style={{width: 120}} className={styles.selection}>实现成果如下:(因为此处我只给第一个<Select>加了className) 批改某一个组件的款式(办法二)留神:这种办法会存在className被css loader编译成哈希字符串的状况,但提供了解决办法实现代码如下: :global{ .select_test{ //给该select框加的className .ant-select-selection{ background-color: red; } }}import styles from '../../page.less'//.less文件为上文中定义.select_test所在文件<Select defaultValue="lucy" style={{width: 120}} className={styles.select_test}></Select>此时咱们会发现并不失效,(起因是:className被css loader编译成哈希字符串)解决办法:(为了对立代码和浏览器class的统一,将select的className的增加形式换了一下) <Select defaultValue="lucy" style={{width: 120}} className="select_test"></Select>问题解决: (未完!) 参考资料:怎么批改antd默认款式及遇到的问题批改ant design 默认css款式 了解尚浅,望不吝赐教!
刚刚理解了费曼学习法,我认为有必要记录在我的项目开发中遇到的问题,进而不断丰富本人的教训。本篇文章用于记录在我的项目过程中遇到的问题及解决方案,进一步加深印象。 问题一:JavaScript数组在React中Setstate后数据变动但不渲染的问题及解决方案问题形容:如下图,基于Ant Design的Table组件进行数据渲染,同时实现点击后数据上移、下移、删除的操作。解决思路:通过点击回调函数获取到惟一标识符key值即序号。遍历数组判断是不是边界数据,即:上移时被点击的数据如果不是第一个、点击下移时的数据如果不是最初一个,则找到该条数据执行如下操作:被点击上移的key-1,被点击的数据上一条key+1后,依据key值排序,从而实现上移、下移的性能。性能实现代码如下: dealTableDataUp(text) { const {tableData} = this.state; let [...tableDataChange] = tableData; for (let i = 0; i < tableDataChange.length; i += 1) { if (i > 0) { if (text.key === tableDataChange[i].key) { tableDataChange[i].key = tableDataChange[i].key - 1; tableDataChange[i - 1].key = tableDataChange[i].key + 1; } } } tableDataChange = this.doSrotByAttribute(tableDataChange, `key`); this.setState({tableData: tableDataChange}); } dealTableDataDown(text) { const {tableData} = this.state; let [...tableDataChange] = tableData; for (let i = 0; i < tableDataChange.length; i += 1) { if (i !== tableDataChange.length - 1) { if (text.key === tableDataChange[i].key) { tableDataChange[i].key = tableDataChange[i].key + 1; tableDataChange[i + 1].key = tableDataChange[i].key - 1; } } } tableDataChange = this.doSrotByAttribute(tableDataChange, `key`); this.setState({tableData: tableDataChange}); } dealTableDataDelete(text) { const {tableData} = this.state; let [...tableDataChange] = tableData; let flag = false; for (let i = 0; i < tableDataChange.length; i += 1) { if (flag === true) { tableDataChange[i].key = tableDataChange[i].key - 1; } if (flag === false) { if (text.key === tableDataChange[i].key) { flag = true; tableDataChange.splice(i, 1); i -= 1; } } } tableDataChange = this.doSrotByAttribute(tableDataChange, `key`); this.setState({tableData: tableDataChange}); }//排序代码 doSrotByAttribute(arr, attribute) { function compare(propertyName) { return function (object1, object2) { const value1 = parseFloat(object1[propertyName]); const value2 = parseFloat(object2[propertyName]); if (value2 < value1) { return 1; } if (value2 > value1) { return -1; } return 0; } } arr.sort(compare(attribute)); return arr; }数据变动但不渲染问题起因:在Java Script中数组作为援用数据类型,定义的数组存储的是其首地址,而数据局部的变动是在堆中,因而当咱们从新SetState时,尽管console.log()的数据曾经变动了,然而不会从新进行渲染,因而不会显示。数据变动但不渲染问题解决办法:对原数组进行深拷贝,应用深拷贝后的数据进行SetState,此时原援用地址产生扭转,则会从新渲染。代码如下: ...
导读: Web IDE的开发素来是整个大数据平台开发中十分简约和轻便的一环,从零搭建一个 Web IDE 通常意味着大量的殚精竭虑和苦思冥想,工夫老本更是不可计数。两个UI组件库一起用更是bug的代名词,有没有什么方法能解决这个问题呢? 你能够看到 ▫ 一个新的web UI轻量级框架 ▫ 同用IDE组件库和antd产生的抵触如何解决 ▫ 它们如何在Taier上完满配合 Keep It Simple, Stupid. 这是开发人耳熟能详的 KISS 准则,也像是一句有调侃象征的善意揭示,揭示每个前端人,简洁易懂的用户体验和删繁就简的搭建逻辑就是前端开发的至简小道。 这也是袋鼠云数栈前端开发团队谋求的指标。 数栈是一个专一一站式产品体系,笼罩数据全链路开发流程,全面国产化兼容,外围源码自主可控的云原生一站式大数据开发治理平台。 2021年12月16日,基于数栈多年大数据开发教训的根底积淀出的轻量级 Web IDE 组件库,Molecule 开源。2022年2月22日,将Molecule 作为其中一个重要 UI 组件搭建出的分布式可视化的 DAG 任务调度零碎——Taier,也紧锣密鼓退出了开源社区。 在Taier通过数百家企业客户的生产环境实战测验之后的明天,咱们想用明天这篇文章跟大家分享一些在 Taier 的搭建过程中时遇到的Molecule 与antd如何适配的解决教训和它们在 Web IDE 开发中的实战体现。 【GitHub开源地址】 https://github.com/DTStack/Taier https://github.com/DTStack/mo... 何为Molecule与TaierTaier 是数栈搭建的一个可视化 DAG 任务调度零碎,其搭建初衷是为了让大数据开发工程师能够将精力集中在业务逻辑的开发上,而不必被工作盘根错节的依赖关系捆住手脚。这一指标就要靠其中 Web IDE 的局部实现。 而在数栈平台与日俱增的迭代中积淀而来的Molecule ,作为轻量级的 Web IDE UI 框架,能极大地缩小搭建编辑器的工夫,其具备的扩大(Extension)机制也使它能够轻易地应答各种需要增长。Molecule形象自数栈产品中离线工作的在线编辑配置性能,同时反哺撑持了各个产品中都存在的在线编写 SQL 代码。Molecule在各方面的不俗体现使咱们很快意识到,用Molecule来承当Taier零碎中的IDE组件角色简直是牵强附会。 IDE搭建,为何MoleculeMolecule之前,前端苦Web IDE久矣。 Web IDE的开发素来是整个大数据平台开发中十分简约和轻便的一环,从零搭建一个 Web IDE 通常意味着大量的殚精竭虑和苦思冥想,工夫老本更是不可计数。传统的 IDE 框架相熟门槛高,维护费用大,对保护人员的技术始终都有很高要求。数栈的研发团队对此深有体会,咱们开源的Molecule从最开始就对“开箱即用,保护不便”这个指标十分动摇,从开源以来它也在不断完善,当初咱们能够自信的说,Molecule将Web IDE UI框架做到了轻量级,高延展,在不就义需要可能性的前提下极大地晋升了前端开发体验,是一套具备残缺的解决方案的开发组件框架。 ...
前言今儿遇到了带宽上传文件的攻打(每秒150M+),导致了服务宕机1.5h。排查发现,上传文件没有token的参数。1、需要上传组件增加token 2、为什么要增加token?1)因为能够拦截非平台申请; 2)平台内申请如果异样,能够禁用那个用户; 3、增加组件headers参数1)页面组件<a-upload-dragger v-model:fileList="file" name="file" :action="apiLink" :beforeUpload="beforeUploadFile" :headers="requestHeaders" @change="handleChange"> <p class="ant-upload-drag-icon"> <inbox-outlined></inbox-outlined> </p> <p class="ant-upload-text"> 点击或拖拽到区域上传 </p></a-upload-dragger>2)header 传 tokendata(){ requestHeaders: { Authorization: 'Bearer ' + token //页面token },}
image-20210906111439548 应用过Antd的小伙伴应该很相熟,Antd组件文档有在CodeSandBox和CodePen中关上间接预览和编辑的性能,这么炫酷且实用的性能具体是怎么实现的? codesandbox.io[1] 是一个前端代码的在线编辑器,反对各种不同的框架,能够随时预览代码的运行后果。创立沙盒“在CodeSandBox中关上”是CodeSandbox提供的性能,让咱们能够通过间接调用API来创立CodeSandbox沙盒。 CodeSandbox提供了几种导入到沙盒中预览的形式: 间接应用提供的公共模板从GitHub导入:https://codesandbox.io/s/github应用GitHubBox:将仓库地址中github.com替换为githubbox.comhttps://github.com/Iamxiaozhu... => https://githubbox.com/Iamxiao...装置浏览器扩大,关上GitHub,页面中会增加一个“在CodeSandBox中关上”的按钮通过命令行从本地导入: npm install -g codesandboxcodesandbox ./通过调用API形式创立沙箱[2]: CodeSandbox提供了通过API让咱们能够通过编程的形式来创立sandbox。咱们能够在文档里通过示例代码来创立sandbox,不便用户编辑和查看。 通过Get和Post申请调用https://codesandbox.io/api/v1/sandboxes/define,即可实现创立CodeSandbox沙箱。 Define API Get调用Demo[3] Post调用Demo[4] Important:CodeSandBox官网Demo[5] Antd中示例代码跳转CodeSandbox、CodePen等:模板示例[6] 嵌入SandBox[7]CodeSandBox还反对间接嵌入:在文档,博客和其余网站中嵌入沙箱,能够展现代码和预览成果: 嵌入SandBox 以官网Demo[8]为例: 点击Share,这里抉择Embed 嵌入SandBox 自定义展现内容和主题,复制嵌入代码就能够了,是通过iframe标签来嵌套页面。 嵌入SandBox配置 相似CodeSandBox的在线编辑器有很多,比方:CodePen[9]、StackBlitz[10]、JSFiddle[11]、JSBin[12]、JSRun[13]等。 微软和GitHub也都推出了本人的在线代码编辑器(和下面几个不同,只提供了代码编辑性能,无奈实时预览): Online VS:https://online.visualstudio.com/GitHub CodeSpaces: https://github.com/features/c...其余相干:Code-Server[14]这里举荐一个能够自定义部署的在线代码编辑器:Code-Server。实际上就是VSCode的在线版本,反对装置VSCode插件,内嵌Terminal中会间接在服务器端运行,十分弱小。 Code-Server在线编辑器示例 Sandpack[15]Sandpack 是 CodeSandbox 的浏览器打包器。 demo 参考资料[1]codesandbox.io: https://codesandbox.io/ [2]通过调用API形式创立沙箱: https://codesandbox.io/docs/i... [3]Get调用Demo: https://codesandbox.io/s/6yzn... [4]Post调用Demo: https://codesandbox.io/s/qzlp... [5]CodeSandBox官网Demo: https://codesandbox.io/exampl... [6]模板示例: https://hub.fastgit.org/ant-d... [7]嵌入SandBox: https://codesandbox.io/docs/e... [8]官网Demo: https://codesandbox.io/s/reac... [9]CodePen: https://codepen.io/ [10]StackBlitz: https://stackblitz.com/ [11]JSFiddle: https://jsfiddle.net/ [12]JSBin: https://jsbin.com/ [13]JSRun: http://jsrun.net/ ...
1- 官网给的解释然而当我增加getPopupContainer 之后,定位任然生效 解决: .tel-box { width: 140px; display: inline-block; position: relative;}
FormItem中设置select的initialtValue【状况形容】:编辑表单时,须要回显数据。【解决方案】:select的option已设置过value和label。只须要将详情接口的value赋值给initialtValue,他会主动显示对应的label。如果找不到,就间接显示这个value。
<a-table ref="table" size="middle" bordered rowKey="jobid" :columns="columns" :dataSource="jobList" :pagination="ipagination" :loading="loading" @change="handleTableChange"><span slot="departid" slot-scope="text"> {{ text | departFilter }} </span><span slot="action" slot-scope="text, row"> <a @click="handleEdit(row)">编辑</a> <a-divider type="vertical"/> <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(row.jobid)"> <a>删除</a> </a-popconfirm> </span> </a-table>rowkey,惟一,多选等下拉框时应用dataSource,对应的json数组columns对应json返回的列名通过过滤器,把id转化为name,在页面显示slot-scope="text, row" row传的是以后行的数据也能够像删除性能相似的传row.id<span slot="state" slot-scope="text, record"> <span v-for="(item,index) in customsCheckStatuses" :value="item.value" :key="index"> {{record.state==item.value? item.text:""}} </span> </span> <template slot="title" slot-scope="{title}"> <span v-if="title.indexOf(searchValue) > -1"> {{title.substr(0, title.indexOf(searchValue))}} <span style="color: #f50">{{searchValue}}</span> {{title.substr(title.indexOf(searchValue) + searchValue.length)}} </span> <span v-else>{{title}}</span> </template>这种形式和filter的输入形式相似,如果逻辑间接,这么解决更容易
<a-modal ref="modalForm" title="人员治理" :width="800" :visible="visible" @ok="handleOk" cancelText="敞开" @cancel="visible = false;" style="top:5%;height: 85%; overflow-y: hidden"> <a-form :form="bizForm"> </a-form></a-modal> 弹出页a-modal标签visible代表是否可见@ok="handleOk" 点击页面的确认按钮,触发的事件cancelText="敞开"勾销按钮显示文字是敞开@cancel="visible = false;"设置属性为不可见:form="bizForm" form里的input表单都绑定到bizForm变量里bizForm: this.$form.createForm(this), 初始化
a-select标签<a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="部门"> <a-select placeholder="请抉择" v-decorator="['departid',{rules: [{ required: true, message: 'Please input your data!' }]}]" > <a-select-option v-for="d in departList" :key="d.departid" :value="d.departid">{{ d.departname }}</a-select-option> </a-select></a-form-item> 整体思路和v-for操作原生的select标签十分相似留神有key和value的值,两个都要有
-应用起来感觉没有elementUI不便 <a-form-item style="display: none;" :labelCol="labelCol" :wrapperCol="wrapperCol" label="id"><a-input placeholder="请输出名称" v-decorator="['personid', {}]" /></a-form-item><a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="名称"><a-input placeholder="请输出名称" v-decorator="['personname', { rules: [{ required: true, message: 'Please input your data!' }] }]" /></a-form-item>减少和批改在一个弹出页里,id须要暗藏a-form-item代表一行labelCol和wrapperCol是页面的布局v-decorator能够写验证信息
ant-design-vue中tree增删改1. 应用背景新我的项目中应用了ant-design-vue组件库.该组件库齐全根基数据双向绑定的模式实现.只有表单组件提供大量的办法.所以,在应用ant-design-vue时,肯定要从扭转数据的角度去切换UI显示成果.然而,在树形控件a-tree的应用上,单从数据驱动下来思考,感体验成果切实不好. 2. 以后痛点通过浏览官网帮忙文档,针对树形控件数据绑定.须要将数据结构成一个蕴含children,title,key属性的大对象.这样一个对象,要么通过后端结构好这样的json对象,要么就是后端给前端一个json数组,前端依据上下级关系构建这么一个树形对象.数据绑定好,就能够胜利的渲染成咱们想要的UI成果了.可痛点在哪里呢? 树形加载胜利后,我要向以后的树形增加一个同级以及上级节点该如何操作(增)树形加载胜利后,我要批改任意一个树形节点该如何操作(改)树形加载胜利后,我要删除一个树形节点该如何操作(删)以上操作,都要求不从新加载树形控件条件下实现.通过测试整顿出了三个可行计划 数据驱动作用域插槽节点事件 3. 数据驱动实现树形节点增删改咱们能够在帮忙文档中找到名为selectedKeys(.sync)属性,sync示意该属性反对双向操作.然而,这里仅仅获取的是一个key值,并不是须要的绑定对象.所以,须要通过这key值找到这个对象.须要找这个对象就相当恶心了 如果后端返回是构建好的数据,须要遍历这个树形数据中找到和这个key值对应的对象.我能想到的就是通过顶层节点递归查找.可是控件都渲染实现了,都晓得每个节点的数据.我为什要从新查找一遍呢???如果后端返回的仅仅是一个数组,这个方才有提到须要从新构建这部分数据为对象.这样查找这个对象又分两种状况 a. 如果列表数据和构建后树形对象采纳克隆的形式,也就是列表中对象的地址和树形中雷同key值对象的地址不同.须要通过办法1遍历从新结构后的树形数据 b. 如果列表数据中的对象和构建后对应的节点是雷同的对象地址.能够间接查找这个列表数据失去对应的对象.所以,恶心的中央就在于构建好一个树,我又得遍历这个树查找某个节点,或者采纳计划b这种空间换工夫的做法 这里咱们假如数据,曾经是构建成树形的数据格式.要实现数据驱动的首要任务须要实现两个外围办法 依据以后节点key值查找节点对象getTreeDataByKey依据以后节点key值查找父级节点children汇合getTreeParentChilds两个办法代码别离如下 // author:herbert date:20201024 qq:464884492// 依据key获取与之相等的数据对象getTreeDataByKey(childs = [], findKey) { let finditem = null; for (let i = 0, len = childs.length; i < len; i++) { let item = childs[i] if (item.key !== findKey && item.children && item.children.length > 0) { finditem = this.getTreeDataByKey(item.children, findKey) } if (item.key == findKey) { finditem = item } if (finditem != null) { break } } return finditem },// author:herbert date:20201024 qq:464884492// 依据key获取父级节点children数组getTreeParentChilds(childs = [], findKey) { let parentChilds = [] for (let i = 0, len = childs.length; i < len; i++) { let item = childs[i] if (item.key !== findKey && item.children && item.children.length > 0) { parentChilds = this.getTreeParentChilds(item.children, findKey) } if (item.key == findKey) { parentChilds = childs } if (parentChilds.length > 0) { break } } return parentChilds},3.1 增加同级节点增加同级节点,须要把新减少的数据,增加到以后选中节点的父级的children数组中.所以,增加节点的难点在如何找到以后选中节点的绑定对象的父级对象.页面代码如下 ...
一:效果图如下:二:实现过程(2-1)通过角色id获取须要要数据因为我这个性能是角色调配权限,所有这里是通过角色id获取已调配的权限菜单以及全副菜单而后在获取到树结构的菜单数据代码如下: /** * 调配权限按钮 */ permissions(row) { this.permissionsConfirmLoading = true getRoleTree(row.roleId) .then(res => { // 获取以后用户角色调配菜单的id data例如:[1002, 1003, 1004, 1213, 1214, 1000, 1001] this.checkedKeys = res.data.data.checkedMenuId // 获取菜单的全副id data例如[1002, 1003, 1004, 1213, 1214, 1000, 1001] this.allMenuIds = res.data.data.menuIds // 这一步是预防用户不点击节点选项间接保留 this.menuIds = res.data.data.checkedMenuId.join(',') return getMenuTree() }) .then(response => { this.treeData = response.data.data this.roleId = row.roleId this.permissionsConfirmLoading = false this.permissionsModalVisible = true }) }(2-2)页面的配置代码如下: <a-modal :visible="permissionsModalVisible" title="调配权限" :width="740" @cancel="permissionsModalVisible = false" > <a-spin :spinning="permissionsConfirmLoading"> <a-tree ref="roleTree" :checked-keys="checkedKeys" :selected-keys="selectedKeys" checkable :check-strictly="checkStrictly" :expanded-keys="expandedKeys" :tree-data="treeData" :replace-fields="{ key:'id' }" @check="onChangePermissionsTree" @select="onTreeNodeSelect" @expand="onExpand" /> </a-spin> <template slot="footer"> <a-dropdown style="float: left" :trigger="['click']" placement="topCenter"> <a-menu slot="overlay"> <a-menu-item key="1" @click="switchCheckStrictly(1)"> 父子关联 </a-menu-item> <a-menu-item key="2" @click="switchCheckStrictly(2)"> 勾销关联 </a-menu-item> <a-menu-item key="3" @click="checkALL"> 全副勾选 </a-menu-item> <a-menu-item key="4" @click="cancelCheckALL"> 勾销全选 </a-menu-item> <a-menu-item key="5" @click="expandAll"> 开展所有 </a-menu-item> <a-menu-item key="6" @click="closeAll"> 合并所有 </a-menu-item> </a-menu> <a-button> 树操作 <a-icon type="up" /> </a-button> </a-dropdown> <a-button @click="permissionsModalVisible = false"> cancal </a-button> <a-button type="primary" @click="permissionsModalSubmit"> ok </a-button> </template> </a-modal>(2-3)对应的办法代码如下: ...
Ant Design Editable Tree TableAnt Design of React - Editable Tree Table可编辑的树形表格 Need in the work, but i did not find ready-made components easy to understand after Baidu and Google.工作中须要,但百度谷歌后并没有发现现成的、可用的、易了解的组件。 So i try to do it.所以我本人尝试写了下。 installrecommend using yarn举荐应用 yarn yarnbuildnpm run buildexample GitHubhttps://github.com/blueju/ant-design-editable-tree-table
前言React 15.x 升 React 16.x 是一次内部重构,对于使用者来说,原来的使用方式仍然可用,额外加了新的功能;而Antd 3.x 升 Antd 4.x, 在我的认知范围里,可以称作是飞(po)跃(huai)性的重构, 因为以前很多写法都不兼容了,组件代码重构,使用者的代码也得重构。但这次重构解决了3.x的很多问题,比如: 由于Icon无法按需加载导致打包体积过大;由于Form表单项变化会造成其他表单项全量渲染,大表单会有性能问题;时间库moment包体积太大。说这么多,还是直接来张图吧,我个人项目的打包体积变化:Antd 3.x VS Antd 4.x 升4.x之后,gzip少了150kb,也就是包大小少了500多kb,这不香么。关于升级我和我的小组,为了用更爽的方式来开发迭代,针对于antd的Form和Table等组件做了一些简单的二次封装,形成了组件库antd-doddle。虽然Antd 4.x推出快小半年了,受疫情影响,今年业务迭代比较缓慢,没有新系统,也觉得暂时没必要去重构业务代码,所以一直只关注不动手。最近比较闲,组件库针对Antd 4.0做了适应性重构,作为一个胶水层,最大程度的去磨平4.0版本Form这种破坏性变动,减少以后业务代码升级4.x版本的调整量。 Antd 4.x到底做了哪些变化,在官方文档可以看到。 这篇文章主要讲针对于4.x Form的变化,我重构组件库的思路。 Antd-doddle 2.x文档地址, 支持4.x: http://doc.closertb.site, 首次加载较慢,请耐心等候。 Antd-doddle 1.x文档地址, 支持3.x: http://static.closertb.site, 首次加载较慢,请耐心等候。 试用项目Git 地址 项目在线试用地址, 请勿乱造 FormGroup重构思路Form组件变化4.x 中除了Icon,最大的更改就在于Form,我自己感受到的变化是: 舍去了Form.create高阶组件包裹表单的写法,而改采用hooks或ref的方式去操作form实例;以前每个表单组件的数据绑定是通过getFieldDecorator这个装饰方法完成,现在改由FormItem来完成;初始values设置,以前是通过getFieldDecorator设置,并且是动态的,即value改变,表单值跟随改变。现在是在Form最外层设置,但是以defaultValue形式设置,即value改变,表单值不跟随变化;最大的改变就是增量式更新,3.x版本,任意表单项改变,都会造成Form.create包裹的全部表单项重新render,这是非常大的性能消耗;而4.x之后,任意表单项改变,只有设置了shouldUpdate属性的表单项有可能执行render,类似于React 16新增的componentShouldUpdate;根据上面的变化点,由外向内层层剖析,针对性的做重构; FormGroup的变化由于以前FormGroup组件,除了收集form方法和公共配置,也作为一个标识,接管了组件内部的渲染层;3.x版本其form实例由Form.create,即业务代码提供;4.x与其相似,只不过是通过hooks生成form实例。 变化点主要在于4.x版本Form要提供initialValues的设置,且这是一个defaultValue的设置,所以我们需要拓展,让其支持values为异步数据时,表单项的值能跟随其改变, 其原理很简单,监听value的变化,并重置表单数据,实现代码如下: // 伪代码,只涉及相关改动const FormGroup = (props, ref) => { const { formItemLayout = layout, children, datas = {}, ...others } = props; // 兼容了非hooks 组件调用的写法,内部再声明一个ref, 以备用; const insideRef = useRef(); const _ref = ref || insideRef; const formProps = { initialValues: {}, // why ...formItemLayout, ...others }; // 如果datas 值变化,重置表单的值 useEffect(() => { const [data, apiStr] = Type.isEmpty(datas) ? [undefined, 'resetFields'] : [datas, 'setFieldsValue']; // 函数式组件采用form操作; if (props.form) { props.form[apiStr](data); return; } // 如果是类组件,才采用ref示例更新组件 if (typeof _ref === 'object') { _ref.current[apiStr](data); } }, [datas]); return ( <Form {...formProps} ref={_ref}> {deepMap(children, extendProps, mapFields)} </Form>);};上面有句代码 initialValues: {},会让人困惑, 为什么没有赋值为datas呢;这个又是antd的一个隐藏知识点,举个例子: ...