基於React的表單開發的分析(上)

giovanni發表於2019-03-04

本文主要講解後臺系統與表單相關的頁面開發,並分析如何才能更好地、高效地開發。

技術棧

  • React
  • Antd

背景

Antd

以下我都將Ant Design 簡稱為 Antd

Ant Design是個服務於企業級產品的UI框架,主要可以用於中後臺系統,它有基於React、Vue和Angular的實現。個人感覺Antd還是很強大的,API相當完善、全面,基本能實現你想要的各種功能。

表單
在開發普通的後臺系統時,開發得最多的就是實體的 新建、編輯和詳情頁面,這三個頁面有共通之處,也有不同之處,感覺有可以複用的地方,但是有些地方又需要特殊處理。

表單頁如圖:

基於React的表單開發的分析(上)
詳情頁如圖:

基於React的表單開發的分析(上)

新建、編輯、詳情頁與Form表單元件的關係

基於React的表單開發的分析(上)

從上面的幾個圖中我們看出:

  • 新建和編輯可以複用一個Form元件
  • 新建時不傳給Form元件資料
  • 編輯時會請求後端實體的資料,傳給Form元件,進行資料初始化
  • 詳情頁照理說也可以用Form元件,但是,UI檢視上面Form元件和詳情頁面會不一致,比如:詳情頁只是純粹展示的div,而非各種表單控制元件了。

思考並進行實現

通過上面的調研,我們可以考慮把詳情頁、新建和編輯做成單獨的頁面,但是新建和編輯複用同一個Form元件,Form元件進行資料收集、展示、表單校驗,額外的邏輯處理(比如新建、編輯的提交動作、跳轉頁面和資料過濾)可能會有不同,所以在新建、編輯頁面進行分別的處理。
ok,我們看看Form表單程式碼實現: 更多詳情看這裡

      <Form onSubmit={this.handleSubmit}>
        <FormItem
          {...formItemLayout}
          label="E-mail"
        >
          {getFieldDecorator('email', {
            rules: [{
              type: 'email', message: 'The input is not valid E-mail!',
            }, {
              required: true, message: 'Please input your E-mail!',
            }],
          })(
            <Input />
          )}
        </FormItem>
        <FormItem
          {...formItemLayout}
          label="Password"
        >
          {getFieldDecorator('password', {
            rules: [{
              required: true, message: 'Please input your password!',
            }, {
              validator: this.validateToNextPassword,
            }],
          })(
            <Input type="password" />
          )}
        </FormItem>
...
複製程式碼

上面的程式碼是利用Antd表單實現的,這裡會有一些問題:

  • 平均一個表單控制元件用平均12~17行程式碼(不包含複雜邏輯和回撥函式),在大型系統中,一個複雜的表單可能會有30~40個控制元件,怎麼辦? 寫一個2000+行的Form.js檔案嗎?
  • 如下寫法,會出現冗餘程式碼:

每個控制元件都要寫FormItemgetFieldDecorator ,會出現多次,而且格式一致

        <FormItem
          {...formItemLayout}
          label="E-mail"
        >
          {getFieldDecorator('email', {
            rules: [{
              type: 'email', message: 'The input is not valid E-mail!',
            }, {
              required: true, message: 'Please input your E-mail!',
            }],
          })(
            <Input />
          )}
        </FormItem>
複製程式碼
  • 詳情頁需要重寫一套完全不一樣的邏輯和UI,無法複用Form元件中的邏輯
  • 如果有動態標籤怎麼辦? 比如我遇到一個場景:頁面中有一些欄位是前端寫死的,比如 使用者名稱,密碼等,還有一些欄位,是使用者上傳一個模板檔案,後端解析模板並返回給前端的,結構可能是這樣:
{
    "name":"標籤名1",
    "type":1, // 1:文字框, 2:百分比,3:數字,4:金額,5:單選按鈕,6:單選下拉框,7:多選按鈕,8:多選下拉框,9:日期-單日,10:日期-區間
    "commonUse":true, //是否常用標籤
    "requiredTag":true, //是否必填
    "placeholder":"這個是描述",
    "option":[ //選擇項會用到此欄位
        {
            "id":1,
            "name":"名字",
            "defaultOption":true, // 是否預設選中
        }
    ]
}
複製程式碼

更好的解決方案

  • 為了避免一個Form超過1000行這種情況出現,我們應該把大型Form表單進行拆分

如下圖,有個合同的Form表單,我們按照型別做如下拆分:

基於React的表單開發的分析(上)

  • 針對上面的其餘問題,我們計劃提取出這樣一個公共元件:
    • 元件接收:需要渲染表單的欄位、初始資料、欄位的控制元件型別等
    • 能根據欄位的不同的控制元件型別渲染不同的表單控制元件
      • Select
      • Input
      • ...
    • 詳情頁也能複用這個元件
    • 具有可擴充套件性(比如Antd的API的方法在此元件中均能使用)

總結

後臺系統中我們開發的大部分頁面都是表單頁(新建、編輯、詳情),少部分是列表頁,我們應該多考慮路由劃分、資料層設計、業務元件拆分、公用元件設計與實現,如果這些方面做好了,積累一定的經驗,以後開發後臺系統一定會事半功倍。
Tip: 我準備在下期再詳細講解上面提到的表單公用元件的設計與實現。
下一期: => 基於React的表單開發的分析(下)

相關連結

ant.design/components/…

相關文章