react->Ant Design->form表单控件按需加载实现

最近在折腾react,因此,将一些本身碰到的问题以及对应的解决办法分享出来,期待和你们共同探讨和进步!

概述

react折腾系列之一:如何在ant框架下,Form表单中实现getFieldDecorator包装控件的按需加载。react

文笔有限,代码才是程序员的真爱。相信看完下方的几行简单的代码和其中的注释,你们对本文要描述的问题,会有比较清晰的了解。git


ps:固然,不少状况下,你可能只须要实现路由组件的按需加载即可,无需涉及这么精细化的小组件操做,那么请不要纠结,本文偏重技术问题探讨,至于应用场景,可灵活自行抉择。程序员

思路

问题清晰了,那么接下来着手解决以前,得有个大概的思路:github

  1. 上网查找相关资料
  2. 上github看是否有相关实例参考
  3. 此处省略n中方法
  4. 自行撸代码

针对该问题,其实比较难找到对应的资料和实例(可能确实这样的需求很少吧)。因此只能自行撸代码了,其实粗略想一想,应该不难,找个现成的react延迟加载组件还不容易啊。相信这个难不倒你们,接下来以你们比较熟悉的react-loadable为例。shell

步骤一:react-loadable用起来

代码大体以下,比较简单,也不须要注释了,具体可查看官方文档和实例。缓存


代码撸完,跑起来看看,不看不知道,一看吓一跳。。。bash

  1. 延迟加载的Input,每次输完一个字符就失焦了,须要再次点击获焦才能输入第二个字符
  2. 延迟加载的Select,选完后,其余的控件(例如Input输入)一操做,该Select有闪烁效果
  3. 偶现的Form重置失效
  4. 。。。
彻底不能接受是否是

必须解决是否是网络

so,react-devtools看一下:框架



看起来,一切正常,该有的props和state都有啊!编辑器

好吧,没办法,又找不到现成的资料和项目参考。看来只能放大招了,看源码!


上面,是react-loadable的一部分源码。因此,ant中的getFieldDecorator包装后,一旦Form中的任何一项组件(Input之类的)值改动(onchange),Form要更新,便会引发全部组件从新生成。

对应到react-loadable的代码,即是:任何一个控件(例如Input)触发onchange,Form更新,全部控件从新进constructor,执行对应的init,而后render,第一次render进第一个if,第二次render进第二个if。

验证很简单,在react-loadable的render方法中,把state打印出来:

this.state-- {error: null, pastDelay: true, timedOut: false, loading: true, loaded: null}
this.state-- {error: null, pastDelay: true, timedOut: false, loading: false, loaded: Module}复制代码

重点看loading和loaded字段,每次onchange都会经历一次loading从true到false的过程。

看完react-loadable源码,问题理清楚后,大招不能停,解决思路:

  1. 不使用getFieldDecorator,自行添加onchange实现相关逻辑
  2. 封装react-loadable,避免每次重走constructor->load
  3. react-loadable自己不适合此种场景,从新找一个,或者本身造一个轮子
方法一,有兴趣自行实践,纯属理论分享,笔者本身也没折腾过!

步骤二:react-loadable封装

代码以下,挺简单的改动,每次加载完的组件,存起来,重复使用。

虽然react-loadable也进行了缓存,可是只是进行了网络请求缓存,每次都会从新走load流程,只是第二次过程很快而已,而解决的思路是直接进行组件缓存。

因为掘金的富文本编辑器复制后换行失效,若是须要看此处源码的,能够点击此处查看


步骤三:本身造轮子

能够考虑本身造一个自己就支持组件级别缓存的loadable组件,并且react-loadable自己的源码有三百多行,可能有挺多咱们不须要的功能。

  1. 本身造轮子,从三百多行到二十多行
  2. 较好的封装,随意切换(即当你想切回react-loadable的时候,能够低成本切换)

因为掘金的富文本编辑器复制后换行失效,若是须要看此处源码的,能够点击此处查看


用起来也方便:

import loadable from './my-loadable'
function getLoadableComponent(componentName) {
    return loadable(() => import('../form-items/' + componentName), null, null, componentName)
}
export default getLoadableComponent复制代码

码字不易,以为此文对你有帮助的,麻烦点个赞鼓励鼓励。

相关文章
相关标签/搜索