Form 資料形式配置化設計
表單資料形式配置化設計
在日常的頁面開發中,表單是和我們打交道非常多的名詞。你是否遇到過自己寫的 input 提示文案被測試或 UED 糾正過、是否看到同樣的校驗電話號碼的正則在團隊裡各有各樣。是否希望這些可以規範起來呢?答案是肯定的!
表單展示屬性的關係
例如一個簡單的電話輸入框,有提示暗文 placeholder,校驗規則的提示資訊;再如一個選擇框,它亦也有提示暗文、校驗規則的提示資訊。咋看之下這個什麼暗文呀!什麼校驗提示好像沒什麼關係。觀察下圖,輸入框的暗文提示就是元件本身所表達的意思請輸入,必填的校驗提示資訊則是元件本身含義 + 業務的名稱(及表單元件的label屬性)。其他型別的校驗則提示和校驗規則相互繫結。
流程中表單資料形式
在具有流程節點的頁面中,資料的形式是隨節點變化的。如第一個節點的資料只能在第一個節點是表單元件形式可編輯的,而在其他節點雖然可以看到第一節點的資料,但卻是純文字的形式。這些從表單元件形式資料到文字形式資料的存在如下的對映關係。
表單元件 | 純文字 | |
---|---|---|
input | 輸入的文字 | |
textArea | 輸入的文字 | |
select | 選擇key 的對應label文字,多選情況下一般用分號分割各key對應的label文字 | |
inputNumber | 輸入的數字文字 | |
... | ... |
表單資料收集
在 react + antd 技術棧下,資料收集可以使用表單元件的 onChange 事件收集到你想要存放的變數上,其次是使用 Form 元件提供的資料收集能力。其中 Form 元件提供的資料收集能力並不只侷限對原有常見表單元件,還有自定義的表單元件。舉個較為特別的:chestnut:如下圖的 FormText 元件,Form 可以幫你收集文字形式展示的內容。當然這種表單文字元件只要不是你的 UI 小夥伴要求用來代替表單其他元件的 readonly/disabled 形式的話,就只有透傳資料或處理時簡化資料讀取。
/** * 用於 Form 表單內部受控展示文字 */ export default class FormText extends Component { render() { const { value, formatMethod = a => a, defaultText = '-', ...resetProps } = this.props; return <span {...resetProps}>{formatMethod(value) || defaultText}</span>; } } // 使用 <FormItem label="姓名"> {getFieldDecorator('name', { initialValue: 'egg', })(<FormText />)} </FormItem>
形式對映異常
我們都知道表單多行文字輸入框一般都會輸入很長很長的文字,但其自身有著已被大家認可的滾動樣式等。但將一段很長的文字框資料展示為文字資料時,你會看到你整個視窗都在展示這個欄位的資料。當然這只是形式變換中的一個較明顯的差異,如何正確變換需我們同 UI 小夥伴一起努力制定一套規範。如當前這個問題就可以給文字一個高度讓他也滾動也不是不行。
配置化的設計方案
經過前面的敘述,童鞋們應該對怎樣設計有了大致的輪廓。主要就是表單元件的選擇、使用什麼形式收集資料、如何對映為 UI想要的文字形式。整體結構如下:
1、形式選擇(表單元件 or 文字)
const renderDataForm = (form, conf = {}) => { // customRenderText 自定義文字形式 const { dataForm = 'form', customRenderText } = conf; return ( <FormItem label={conf.label} {...conf.formItemProps} > {dataForm === 'form' ? renderFormItem(form, conf) : customRenderText ? customRenderText(conf) : renderText(conf) } </FormItem> ); };
2、表單元件選擇
export const renderFormItem = (form, rest) => { const { getFieldDecorator } = form; const { label = '', field = '', formItemType = 'input', initialValue, required = true, rules = [], ...itemRest } = rest; return (getFieldDecorator(field, { initialValue: renderInitialValue(initialValue, formItemType), rules: [ // 必填提示 { required, message: renderMessage(formItemType, label) }, ...rules, ], ...(formItemType === 'upload' ? { getValueFromEvent: (e) => { if (Array.isArray(e)) { return e; } return e && e.fileList; }, valuePropName: 'fileList' } : {}), })( renderItem(formItemType, itemRest) )); }; // 選擇表單元件 const renderItem = (formItemType, itemRest) => { const { CustomFormItem } = itemRest; let item = <Input placeholder="請輸入" {...itemRest} />; switch (formItemType) { case 'textArea': item = <TextArea placeholder="請輸入" {...itemRest} />; break; // ...code // 自定義表單元件 case 'customFormItem': item = (CustomFormItem ? CustomFormItem() : <FormText />); break; default: } return item; };
3、對映文字
export const renderText = (rest) => { const { formItemType = 'input', initialValue, selectOptions = [], selectMode = '', options = [] } = rest; switch (formItemType) { case 'radioGroup': return (options.find(item => item.value === initialValue) || {}).label || '-'; case 'datePick': const { format = 'YYYY-MM-DD HH:mm:ss' } = rest; return initialValue !== undefined ? moment(initialValue).format(format) : '-'; // ...code default: return bizStringFormat(initialValue); } }
4、通用校驗規則整理
export const postCode = /^[0-9]{6}$/; export const phone = /^1\d{10}$/; // ...code // form rules export const postCodeRule = { pattern: postCode, message: '請輸入6位數字', }; export const phoneRule = { pattern: phone, message: '請輸入11位號碼', }; // ...code
5、使用 已實現文章最上面的圖列效果為例,如下
const Demo = (props) => { const { form } = props; // 因為資料的形式預設為表單,所以 dataForm: 'form' 可不配置 const formConf = [{ label: '郵箱', feild: 'email', rules: [emailRule], // emailRule 為郵箱校驗規則 }, { label: '地址', field: 'addr', formItemType: 'textArea', maxLength: 50, }, { label: '排序', field: 'sort', formItemType: 'select', selectOptions: [{ value: 'up', label: '升序' }, { value: 'down', label: '降序' }] }]; // 將配置遍歷傳入renderDataForm // 當然你也可以封裝成組建,直接向組建傳入 form、formConf,減少遍歷的重複書寫和整潔 return formConf.map(item => renderDataForm(form, item));
結束語
至此,本文設計了一套基礎表單的配置功能,主要目的是提升表單使用的規範化、區分和理解前端資料的形式。
❉ 作者介紹 ❉

- 淺談低程式碼平臺遠端元件載入方案
- 前端富文字基礎及實現
- 淺談前端埋點&監控
- 如何讓 x == 1 && x == 2 && x == 3 等式成立
- 淺析 path 常用工具函式原始碼
- web components-LitElement實踐
- 模組聯邦淺析
- 效能優化——圖片壓縮、載入和格式選擇
- 如何基於 WebComponents 封裝 UI 元件庫
- CDP 遠端除錯方案
- 如何落地一個智慧機器人
- Form 資料形式配置化設計
- Lerna 執行流程剖析
- Decorator 裝飾器
- 淺析snabbdom中vnode和diff演算法
- 函數語言程式設計(FP)
- 如何利用 SCSS 實現一鍵換膚
- 淺析FormData
- Flutter For Web 編譯的兩種方案
- Web 多執行緒開發利器 Comlink 的剖析與思考