記錄使用AntDesign開發,一個月的心理路程.難點:動態獲得輸入框相加減後的值,步驟條父組件子組件相互傳值.

背景:十月十二日進入了新公司.負責PC端.使用技術:AntDesign,React,dva.分配的項目模塊是財務回款.AntDesign中涉及到的組件有:
Button按鈕 Icon圖標 Text文本 Title標題 Grid柵格 Form表單 Pagination分頁 Steps步驟條 Checkbox多選框 DatePicker日期選擇框 Input輸入框 InputNumber數字輸入框 Radio單選框 Select選擇器 Badge徽標數 List列表 Tag標籤, Table表格 Drawer抽屜 Message全局提示 Result結果 Spin加載中 Search搜索 Divider分割線 Descriptions描述列表
歷經一個月.如今已開發聯調完畢.成功上線.今天恰好有時間,整理下本身遇到的難點和解決思路.git

開發第一步,先看UI設計圖和項目文檔,瞭解客戶需求與頁面邏輯.
開發第二步,開始繪製靜態頁面.

由於是新的項目,因此項目小組長會給一個git地址,上面有一個空的antd的架子.直接從git上拉下來在這個空架子裏開發就好.若是不會從git上拉取項目的能夠看這裏git命令
,由於一個項目有多個模塊,這樣你們每次都是在同一個環境下開發的.因此用一個git地址.每一個人每次寫完本身的頁面後就提交代碼合併就行了.
這個是antd pro 的項目目錄:
image.png
簡單介紹下經常使用的文件夾:
config裏面是路由
mock是模擬接口的
public裏面放圖片
頁面在src下面寫.
三層結構.services,models,pages.
services裏面是鏈接後端接口的
models是把拿到的接口數據轉換爲使用的數據
pages裏面是頁面層,畫頁面,調接口,跳轉頁面等操做.
util裏面是工具.
基本上經常使用的就是這些.上家公司是把全部的model都統一寫在model層裏,全部的services都寫在services裏.如今這家公司.我發現他們都是在一個文件夾裏面.寫本身的model和services.就像這樣:
image.png
.js文件裏面就是寫頁面和邏輯的地方,頁頭引入組件,class上面引入model層,引入Form,裏面寫你的state,還有方法,render裏面寫return.
image.png後端

image.png
.less裏面是頁面樣式,就像這樣,直接寫.
image.png
model層裏面是接口返回的值.
關注的點有:
namespace.就是你定義的你的model層的名字
effcts裏面就是你獲取的接口的值.能夠在這裏處理接口調成功後的邏輯.callback.
reducers裏面就是你的異步方法返回值.
image.png
srvice裏面是鏈接後端接口的.
image.png
基本上開發一個頁面,文件夾下就是這四個文件.
在這裏,我遇到了第一個問題,就是頁面較爲複雜,好比有步驟條的頁面,代碼寫着寫着就1000行了.整個頁面代碼不少,不利於管理.後面請教了同事.學會了分割頁面,把一個步驟條做爲一個子組件,放在一個父組件裏面.這時候,目錄就變成了這樣:
image.png
當父組件頁面須要展現子組件的時候,把子組件引用過來.就像這樣:antd

import StepsOne from './components/stepsOne';
import StepsTwo from './components/stepsTwo';
import StepsThree from './components/stepsThree';
import StepsFour from './components/stepsFour';

使用的時候:less

<Steps current={current} className={styles['steps_title']}>
            {steps.map(item => (
              <Step key={item.title} title={item.title} />
            ))}
          </Steps>
          <div className="steps-content">
            {current == 0 && (
              <StepsOne
                getOneListData={listData => this.getOneListData(listData)}
                val={this.state.val}
              />
            )}
            {current == 1 && (
              <StepsTwo
                datalist={datalist}
                getTwoListData={(listDataTwo, data1) => this.getTwoListData(listDataTwo, data1)}
              />
            )}
            {current == 2 && (
              <StepsThree
                datalistTwo={datalistTwo}
                onRef={ref => this.stepThreeRef(ref)}
                aClaimAmounts={aClaimAmounts}
                getThreeNote={note => this.getThreeNote(note)}
              />
            )}
            {current == 3 && <StepsFour aClaimAmounts={aClaimAmounts} datalistTwo={datalistTwo} />}
            {current == 4 && (
              <Result
                status="success"
                title="提交成功"
                subTitle="提交日期 2019-10-15"
                style={{ background: 'white', height: '100%', bottom: '3%' }}
                extra={[
                  <Button key="1" type="primary" onClick={() => this.newApplication()}>
                    填寫新的申請
                  </Button>,
                  <Button key="2" onClick={() => this.goDetails()}>
                    查看詳情
                  </Button>,
                ]}
              />
            )}

可能我寫的比較多.看起來不是很順.大概這樣理解:
把子組件引入後,在須要使用的地方,直接用標籤<StepsOne /> 這樣使用就能夠獲得子組件的內容了.至於個人datalist={datalist} 這個意義是向子組件傳值.{datalist}這裏面的datalist是我把父組件裏的state裏的datalist解析出來的值.異步

getTwoListData={(listDataTwo, data1) => this.getTwoListData(listDataTwo, data1)}

這個意義是子組件向父組件傳值.ide

onRef={ref => this.stepThreeRef(ref)}

這個意義是父組件能夠拿到子組件內全部的值,包括state裏面的.
在使用onRef方法的時候,須要先在子組件內的componentDidMount方法裏面定義:this.props.onRef(this);而後在父組件內才能夠拿到.父組件拿值:
我是在父組件的state裏面定義了一個變量,用來存儲第三個步驟條全部的值.工具

stepThreeRef = ref => {
    this.setState({ threeRef: ref });
  };

這個很繞很繞,靜態頁面我一個禮拜就寫完了.聯調接口的時候,這幾個步驟條加上傳值取值賦值花了我聯調一半的時間,哈哈哈哈.女生嘛,邏輯差了那麼一點點~ 理解起來就會有難度~寫的就慢了~我也是查了N個百度又問了好幾回同事才解決了這些問題.之後多寫寫應該就順了就快了.
其餘的組件都比較簡單,引入後直接使用就行了.可是步驟條和抽屜是有邏輯在裏面的,這兩個組件以前都沒有用過.因此這個項目寫起來仍是花了點時間的.
好比此次我寫項目使用的步驟條邏輯(記錄一下,哈哈哈哈):
image.png
第一個頁面有一個單選列表.使用的組件有Table表格,Tag標籤,Search搜索,Radio單選框
image.png
點擊下一步去第二個頁面的時候,須要把單選後的列表內容所有傳過去.而且這個單選是必選.若是沒有選,就要用Message全局提示彈框.
image.png
第二個頁面,分爲兩部分,展現公司名稱和回款單還有發票.使用的組件有:image.png
image.png
點擊回款詳情是打開一個抽屜,裏面有回款單信息:
image.png
點擊上一步是返回第一個步驟條頁面,而且第一個頁面以前選中的數據要保持選中的狀態.點擊取消也是回到第一個步驟條頁面,不過選中的狀態要取消.點擊下一步去第三個步驟條頁面.須要把第二個頁面的單選回款單和多選發票帶過去.這兩個必須判斷兩個都必選一個,不然彈框,頁面也停留在當前頁.就像這樣:
image.png
兩個都選中後點擊下一步就能夠進入第三個頁面了.
第三個頁面展現的就是第二個頁面傳過來的回款單和發票,而且每一個發票下面有不少個行項目,截圖的是一個,後續會有不少.因此這裏要遍歷展現發票列表.且每一個行項目均可以輸入金額匹配.右下方的本次匹配金額動態增長或減小.好了,在這裏我遇到了個人第二個問題:頁面下方的本次匹配金額如何動態相加減輸入框的金額.輸入框的金額是有方法能夠拿到的.e.target.value.相信通常你們都知道.可是頁面上可能有N個輸入框.這個是不肯定的.後面想到,這個輸入框我是放在Form下面的.image.png.可能我寫的複雜了.可是那時候就是這樣想的.後面同事就給我推薦了Form表單的一個方法,叫這個!!!this.props.form.getFieldsValue();賊好用.一次性給我把頁面的輸入框內容所有獲取到了.並且我還踩坑了,開始綁定的是onChange方法,後面發現有點bug,由於是onChange方法是輸入框值改變的時候才觸發的,若是用戶點擊輸入框後沒有作改變,可是你總值又相加減了,就會有問題.後面用的是onBlur方法.失焦的時候觸發.這樣的就能夠避免用戶點擊輸入框後不作操做也不會影響最終值了.由於我是在方法內把全部的值相加了~ 好吧~ 我以爲稍微有點點蠢,可是沒想到好方法.就用的這個了.最終結果就是本次匹配金額隨着輸入框的值動態相加減.仍是實現了,哈哈哈哈哈.點擊上一步回到第二個頁面,第二個頁面要選中當時來第三個頁面的時候選中的值.第三個頁面用的組件也介紹下:
image.png
判斷邏輯也有不少,好比輸入框值不能大於未匹配,本次匹配總金額不能大於未匹配金額.不然彈框,停留
image.png
所有都符合條件後,點擊下一步成功來到第四個頁面.
這個頁面和第三個頁面不同的點就是輸入框變成了展現,備註也變成了只讀.點擊上一步回到第三個頁面,第三個頁面輸入框要顯示以前輸入的數字,備註也是同樣.
image.png
第四個頁面點擊提交來到第五個頁面.這裏點擊提交的時候是不用作邏輯判斷的,可是要發接口.把全部的參數傳給後端.若是接口返回錯誤了,頁面也會停留.
image.png
這裏介紹了我模塊中最複雜的一個頁面.
其餘的四個頁面就是一些展現數據,搜索,抽屜詳情,跳轉抽屜等等沒啥難度了.
說下跳轉頁面我用方法:this

goDetails = () => {
    const {id} = this.state
    router.push({
      pathname: '/receivableManagement/receivableDetails',
      query: {
        id,
      },
    });
  };

pathname就是頁面路徑,query裏面是傳參.把參數帶到跳轉後的頁面去.取參數就是用query取:spa

// 獲取回款單內容
  getListCompletedMatch = () => {
    const {
      location: { query },
    } = this.props;
    this.setState({ loading: true });
    this.props.dispatch({
      type: 'receivableDetailsModel/getListCompletedMatch',
      data: { paymentId: query.id },
      callback:data =>{
        this.setState({ loading: false });
      }
    });
  };

還有一些小坑坑就不一一訴說了.在這個模塊中收穫最多的就是動態獲得輸入框相加減後的值,還有步驟條父組件子組件傳值.以及抽屜,多個抽屜跳轉.好用的方法有:
給金額後保留兩位小數.Number(amount).toFixed(2);
這個toFixed()方法必定要是Number類型的值,括號裏就是保留的小數位.
輸入框失焦的時候觸發的onBlur方法.能夠取到最後一個值.
獲取Form表單下的所有輸入框值:this.props.form.getFieldsValue()設計

放幾張寫好的頁面~
image.png
image.png
image.png
image.png
image.png
image.png

相關文章
相關標籤/搜索