「功能實現」我封裝了一個表單元件,感覺離財富自由又近了一步
theme: channing-cyan highlight: atelier-lakeside-light
我在封裝詳情頁功能的時候,其實最早的雄心壯志是做低程式碼平臺。看了幾篇文章,再看看自己的小鍵盤以及手裡的專案排期,就放棄了。我和我的夢想終究是隔著時間、人力、能力等多重重險阻。
但是,我轉念一想,如果把前端的功能簡化,不就有時間做低程式碼平臺的開發了嗎?對於自己的機智,反手就是一個贊。
於是開始計劃,最大化的模組化和元件化前端功能,這樣一來,每次新需求開發就會非常的便捷。而後臺系統,最複雜也最囉嗦的就是表單功能,所以我準備將表單做成元件化的。
表單功能不用再重複的碼一些個輸入框、下拉項、日期控制元件等程式碼,是不是節省了很多時間,節省出來的時間又可以去研究低程式碼開發,是不是離財富自由更近了一步。(✧◡✧)
基於React框架開發,使用的antd UI元件庫。
整體設計
功能介紹
antd提供的Form表單控制元件,已經集成了資料錄入、校驗以及對應樣式等。但是我們實際開發的時候,後臺系統的新增、編輯、其他資料錄入等表單彈窗,內容項大多是Input、Radio、CheckBox等,每次開發都重複碼一些程式碼。所以我根據日常開發經驗,將常規的表單項做了進一步的封裝處理。
封裝處理之後,只需將表單項型別、key值等關鍵變數放到一個數組物件中,通過props傳遞到表單元件中即可。
當表單填寫完成之後,填寫的資料會通過callback函式回傳到表單彈窗中。
引數介紹
| 引數 | 說明 | 型別 | 預設值 | | ---------- | ----------- | -------------------- | --- | | data | 表單預設資料 | object | {} | | list | 表單項展示陣列 | any[] | [] | | layout | 表單佈局 | object | - | | callback | 提交操作的回撥函式 | (value,list) => void | | | getFormRef | 獲取formRef方法 | (formRef) => void | |
表單項型別
目前支援的表單項型別如下,未來如果有新的開發思路,會繼續增加
| 型別 | key | | ------ | ----------- | | 輸入框 | input | | 數值型輸入框 | inputNumber | | 日期 | date | | 下拉選擇器 | select | | 多選框 | checkbox | | 單選框 | radio | | 文字域 | textArea | | 純文字展示 | text |
細節處理
細節處理只放關鍵程式碼,完整程式碼已經放到github上了,github地址在文末。下面主要將設計思路和實現方式
型別區分
list陣列,根據每個元素的fieldtype區分不同的展示內容。
js
{
list.map((formItem, formIndex) => {
return (
<Fragment key={formIndex}>
{formItem.fieldtype === 'input' && inputContent(formItem)}
{formItem.fieldtype === 'inputNumber' && inputNumberContent(formItem)}
......
</Fragment>
);
});
}
input
- 輸入框使用的antd提供的Input元件。
- 如果輸入框型別的內容項,展示內容不單單是輸入框,可能還包含其他的比如提示文案,可以使用children進行內容替換。
js
/**
* 輸入框型別
* @param {object} item 表單項
*/
const inputContent = item => {
return (
<>
{item.children ? (
item.children
) : (
<Form.Item label={item.label} name={item.key} rules={item.rules} disabled={item.disabled}>
<Input placeholder={`請輸入${item.label}`} />
</Form.Item>
)}
);
};
inputNumber
- 輸入框使用的antd提供的InputNumber元件。
- 數字型別的輸入框的特別之處在於輸入的數值可以設定最小值和最大值、小數點、每次可以改變的步數。這些都可以通過設定對應的屬性進行控制。
- 數字型別的輸入框支援展示單位,通過unit變數控制單位的展示。
js
<Form.Item label={item.label} className={classnames({ required: item.required })}>
<Form.Item noStyle name={item.key} rules={item.rules} disabled={item.disabled}>
<InputNumber style={{ width: '50%' }} step={item.step} min={item.min} max={item.max} precision={item.precision} />
</Form.Item>
{item.unit && <span style={{ marginLeft: '10px' }}>{item.unit}</span>}
</Form.Item>
date
- 日期型別使用的antd提供的DatePicker元件。
- 日期型別支援不同的時間展示方式,通過format變數實現。
- 日期型別可以設定可選時間範圍,可選範圍包括起日和止日,也可單獨設定起日或止日。
- 寫文件的時候突然意識到,實際日期型別也可以支援日期精確到年或是月或是日,目前元件沒有實現這個功能,後續實現之後再更新文件。(靈感就是這麼一瞬間就來了)
select
- 下拉選擇器型別使用的antd提供的Select元件。
- 下拉選擇器操作一般獲取的是value,如果需要拿到選中的節點文字 label,通過onChange時間設定option變數的值為選擇的下拉項的值。
- 有一種特殊情況,當下拉項選擇其他時,需要輸入其他選項的具體值,所以增加了可輸入其他的文字域功能。
js
{/* 下拉項中有需要文字輸入的情況 */}
{item.textArea.code && item.option.value === item.textArea.code ? textAreaContent(item.textArea) : null}
checkbox
- 多選框型別使用的antd提供的Checkbox元件。
radio
- 單選框型別使用的antd提供的Radio元件。
- 有一種特殊情況,當單選項選擇否或拒絕時,需要輸入原因或者說明,所以增加了可輸入其他的文字域功能。
textArea
- 文字域型別使用的antd提供的Input.TextArea元件。
- 當文字域型別表單項和其他表單項組合展示時,展示的佈局值需要和組合的表單項一致,所以根據type型別做了特殊處理。
js
let areaLayout = {};
if (type === 'other') {
areaLayout = { wrapperCol: { offset: layout.labelCol, span: layout.wrapperCol } };
label = null;
}
text
純展示型別,展示具體內容即可。
如何使用
引入元件
- 一般公共元件會放在components。完整的程式碼已經放github上了,github地址在文末。,這裡不在重複,主要將一下實現思路。
- data,基礎資料物件,裡面放一些表單初始化的資料,比如編輯的時候,表單需要回顯之前填過的資料,所以我把這部分資料放到了data裡面。
- list,這個是重點,它是一個數組物件,放完整的表單資料,所有需要展示的表單項都要放到list陣列中,
- callback,是一個回撥函式,提交表單時,需要請求後端提供的介面進行資料上報。callback函式中的引數value包含所有表單項的操作值。
- getFormRef,是一個操作函式,有一些彈窗的操作按鈕需要特殊處理,不是通過From元件上的onFinish方法進行的操作,所以需要將formRef返回到彈窗中,獲取實際的操作。
```js import BaseFormUI from '@/components/BaseFormUI';
......
const config = { data: { ...data, initFieldsValueFlag: true, }, list: list, getFormRef: getFormRef, callback: callback, };
......
彈窗展示
資料提交
如果後端介面沒有特殊要求,value物件中的資料基本就滿足了,如果需要其他值可以從list中獲取。
總結
github地址: react-antd-manage
功能完成之後,發現沒有自己最開始設想的那麼複雜。當然了,也跟功能的相容程度有關係,不適用特別複雜的表單,比如表格類的表單。
未來希望伴隨著學習和進步,進一步完善表單元件。
我正在參與掘金技術社群創作者簽約計劃招募活動,點選連結報名投稿。
- await-to-js 原始碼分析,體驗一把捕獲異常的優雅
- CSS偽類的第三集,原來偽類也可組CP
- 從:is()說起,開啟CSS偽類第二集
- 一組純CSS開發的聊天背景圖,幫助避免發錯訊息的尷尬
- 「CSS特效」我的發呆專屬,反覆解鎖手機螢幕
- 「技術分享」以Antd為例,快速打通UI元件開發的任督二脈
- 「功能實現」我封裝了一個表單元件,感覺離財富自由又近了一步
- 「經驗總結」高效開發,老程式碼可以這樣動
- 前端開發提效小技巧之業務功能篇
- 人生有忙忙碌碌,也有詩和遠方 | 2022年中總結
- 【端午節】新奇體驗,我用react實現網頁遊戲的全過程(包括規則設計)
- 【暑假記憶】消暑神器,我用CSS復刻了一個遊戲機
- 突圍?我願稱之為向上的攀登者
- 【孟夏之遇】望孟夏之短夜兮,螢星相伴
- 【技術學習】SVG-邊學邊做
- 【TS實踐】自己動手豐衣足食的TS專案開發
- 【碼上掘金】通過FileReader讀取Excel檔案內容
- 【Taro開發】四月芳菲,Taro觀賞指南
- 【Node.js】青梅煮酒,聊聊zlib壓縮
- 【知識點】關於iframe跨域通訊