背景:十月十二日進入了新公司.負責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
由於是新的項目,因此項目小組長會給一個git地址,上面有一個空的antd的架子.直接從git上拉下來在這個空架子裏開發就好.若是不會從git上拉取項目的能夠看這裏git命令
,由於一個項目有多個模塊,這樣你們每次都是在同一個環境下開發的.因此用一個git地址.每一個人每次寫完本身的頁面後就提交代碼合併就行了.
這個是antd pro 的項目目錄:
簡單介紹下經常使用的文件夾:
config裏面是路由
mock是模擬接口的
public裏面放圖片
頁面在src下面寫.
三層結構.services,models,pages.
services裏面是鏈接後端接口的
models是把拿到的接口數據轉換爲使用的數據
pages裏面是頁面層,畫頁面,調接口,跳轉頁面等操做.
util裏面是工具.
基本上經常使用的就是這些.上家公司是把全部的model都統一寫在model層裏,全部的services都寫在services裏.如今這家公司.我發現他們都是在一個文件夾裏面.寫本身的model和services.就像這樣:
.js文件裏面就是寫頁面和邏輯的地方,頁頭引入組件,class上面引入model層,引入Form,裏面寫你的state,還有方法,render裏面寫return.後端
.less裏面是頁面樣式,就像這樣,直接寫.
model層裏面是接口返回的值.
關注的點有:
namespace.就是你定義的你的model層的名字
effcts裏面就是你獲取的接口的值.能夠在這裏處理接口調成功後的邏輯.callback.
reducers裏面就是你的異步方法返回值.
srvice裏面是鏈接後端接口的.
基本上開發一個頁面,文件夾下就是這四個文件.
在這裏,我遇到了第一個問題,就是頁面較爲複雜,好比有步驟條的頁面,代碼寫着寫着就1000行了.整個頁面代碼不少,不利於管理.後面請教了同事.學會了分割頁面,把一個步驟條做爲一個子組件,放在一個父組件裏面.這時候,目錄就變成了這樣:
當父組件頁面須要展現子組件的時候,把子組件引用過來.就像這樣: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個百度又問了好幾回同事才解決了這些問題.之後多寫寫應該就順了就快了.
其餘的組件都比較簡單,引入後直接使用就行了.可是步驟條和抽屜是有邏輯在裏面的,這兩個組件以前都沒有用過.因此這個項目寫起來仍是花了點時間的.
好比此次我寫項目使用的步驟條邏輯(記錄一下,哈哈哈哈):
第一個頁面有一個單選列表.使用的組件有Table表格,Tag標籤,Search搜索,Radio單選框
點擊下一步去第二個頁面的時候,須要把單選後的列表內容所有傳過去.而且這個單選是必選.若是沒有選,就要用Message全局提示彈框.
第二個頁面,分爲兩部分,展現公司名稱和回款單還有發票.使用的組件有:
點擊回款詳情是打開一個抽屜,裏面有回款單信息:
點擊上一步是返回第一個步驟條頁面,而且第一個頁面以前選中的數據要保持選中的狀態.點擊取消也是回到第一個步驟條頁面,不過選中的狀態要取消.點擊下一步去第三個步驟條頁面.須要把第二個頁面的單選回款單和多選發票帶過去.這兩個必須判斷兩個都必選一個,不然彈框,頁面也停留在當前頁.就像這樣:
兩個都選中後點擊下一步就能夠進入第三個頁面了.
第三個頁面展現的就是第二個頁面傳過來的回款單和發票,而且每一個發票下面有不少個行項目,截圖的是一個,後續會有不少.因此這裏要遍歷展現發票列表.且每一個行項目均可以輸入金額匹配.右下方的本次匹配金額動態增長或減小.好了,在這裏我遇到了個人第二個問題:頁面下方的本次匹配金額如何動態相加減輸入框的金額.輸入框的金額是有方法能夠拿到的.e.target.value.相信通常你們都知道.可是頁面上可能有N個輸入框.這個是不肯定的.後面想到,這個輸入框我是放在Form下面的..可能我寫的複雜了.可是那時候就是這樣想的.後面同事就給我推薦了Form表單的一個方法,叫這個!!!this.props.form.getFieldsValue();賊好用.一次性給我把頁面的輸入框內容所有獲取到了.並且我還踩坑了,開始綁定的是onChange方法,後面發現有點bug,由於是onChange方法是輸入框值改變的時候才觸發的,若是用戶點擊輸入框後沒有作改變,可是你總值又相加減了,就會有問題.後面用的是onBlur方法.失焦的時候觸發.這樣的就能夠避免用戶點擊輸入框後不作操做也不會影響最終值了.由於我是在方法內把全部的值相加了~ 好吧~ 我以爲稍微有點點蠢,可是沒想到好方法.就用的這個了.最終結果就是本次匹配金額隨着輸入框的值動態相加減.仍是實現了,哈哈哈哈哈.點擊上一步回到第二個頁面,第二個頁面要選中當時來第三個頁面的時候選中的值.第三個頁面用的組件也介紹下:
判斷邏輯也有不少,好比輸入框值不能大於未匹配,本次匹配總金額不能大於未匹配金額.不然彈框,停留
所有都符合條件後,點擊下一步成功來到第四個頁面.
這個頁面和第三個頁面不同的點就是輸入框變成了展現,備註也變成了只讀.點擊上一步回到第三個頁面,第三個頁面輸入框要顯示以前輸入的數字,備註也是同樣.
第四個頁面點擊提交來到第五個頁面.這裏點擊提交的時候是不用作邏輯判斷的,可是要發接口.把全部的參數傳給後端.若是接口返回錯誤了,頁面也會停留.
這裏介紹了我模塊中最複雜的一個頁面.
其餘的四個頁面就是一些展現數據,搜索,抽屜詳情,跳轉抽屜等等沒啥難度了.
說下跳轉頁面我用方法: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()設計
放幾張寫好的頁面~