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複製代碼

碼字不易,以爲此文對你有幫助的,麻煩點個贊鼓勵鼓勵。

相關文章
相關標籤/搜索