當咱們在作後臺管理系統時,常常會遇到很是複雜的表單:html
- 表單項很是多
- 在各類表單類型下,顯示不一樣的表單項
- 在某些條件下,某些表單項會關閉驗證
- 每一個表單項還會有其餘自定義邏輯,好比輸入框能夠插入模板變量、輸入字符數量顯示、圖片上傳並顯示、富文本。。。
- 在這種錯綜複雜的狀況下,完成表單的驗證和提交
- 能夠查看具體例子:例子中省略了不少瑣碎的功能,只保留總體的複雜表單框架,用於展現解決方案
vue
文件中全部的表單項顯示隱藏、驗證、數據獲取、提交、自定義等邏輯放在一塊兒前端
- 根據表單類型,使用
v-if/v-show
處理表單項顯示隱藏- 在
elementui
自定義驗證中,根據表單類型,判斷表單項是否驗證- 根據表單類型,獲取不一樣的數據,並提交到不一樣的接口
- 其他全部的自定義邏輯
vue
文件,輕輕鬆鬆上2000
行其實很容易想到根據不一樣的表單類型,分離出多個相應類型的子表單。但我在實踐時仍是遇到了不少問題:父子表單驗證、總體提交數據的獲取等等,並總結出一套解決方案:vue
全部的子組件中都須要包含兩個方法validate
、getData
供父組件調用。git
validate
方法用於驗證自己組件的表單項,並返回一個promise
對象github
vaildate() {
// 返回`elementUI`表單驗證的結果(爲`promise`對象)
return this.$refs["ruleForm"].validate();
},
複製代碼
getData
方法提供子組件中的數據c#
getData() {
// 返回子組件的form
return this.ruleForm;
},
複製代碼
使用策略模式存儲並獲取子表單的ref
(用於獲取子表單的方法)和提交函數 。省略了大量的if-else
判斷。promise
data:{
// type和ref名稱的映射
typeRefMap: {
1: "message",
2: "mail",
3: "apppush"
},
// type和提交函數的映射。不一樣類型,接口可能不一樣
typeSubmitMap: {
1: data => alert(`短信模板建立成功${JSON.stringify(data)}`),
2: data => alert(`郵件模板建立成功${JSON.stringify(data)}`),
3: data => alert(`push模板建立成功${JSON.stringify(data)}`)
},
}
複製代碼
submit
方法用於父子組件表單驗證、獲取總體數據、調用當前類型提交函數提交數據前端工程師
由於
elementUI
表單驗證的validate
方法能夠返回promise
結果,能夠利用promise
的特性來處理父子表單的驗證。 好比then
函數能夠返回另外一個promise
對象、catch
能夠獲取它以上全部then
的reject
、Promise.all
。架構
// 父表單驗證經過纔會驗證子表單,存在前後順序
submitForm() {
const templateType = this.typeRefMap[this.indexForm.type];
this.$refs["indexForm"]
.validate()
.then(res => {
// 父表單驗證成功後,驗證子表單
return this.$refs[templateType].vaildate();
})
.then(res => {
// 所有驗證經過
// 獲取總體數據
const reqData = {
// 獲取子組件數據
...this.$refs[templateType].getData(),
...this.indexForm
};
// 獲取當前表單類型的提交函數,並提交
this.typeSubmitMap[this.indexForm.type](reqData);
})
.catch(err => {
console.log(err);
});
},
複製代碼
submitForm1() {
const templateType = this.typeRefMap[this.indexForm.type];
const validate1 = this.$refs["indexForm"].validate();
const validate2 = this.$refs[templateType].vaildate();
// 父子表單一塊兒驗證
Promise.all([validate1, validate2])
.then(res => {
// 都經過時,發送請求
const reqData = {
...this.$refs[templateType].getData(),
...this.indexForm
};
this.typeSubmitMap[this.indexForm.type](reqData);
})
.catch(err => {
console.log(err);
});
},
複製代碼
總結:不少項目我都遇到這種複雜的表單,也用了不少種解決方案,在此總結出了一種比較整潔簡便的方案。固然還有其餘不少方案,好比能夠把數據提交的方法放在每個子組件中,公共的表單項數據經過
props
傳遞給子組件用於提交。有其餘更加簡潔的方案,歡迎評論,或者github
上提issue
app
題外話: 看了前端架構師親述:前端工程師成長之路的 N 問 及 回答中的幾個回答後,對我有很大的啓發。在對本身的技術方向、前景迷茫時、或者在埋怨本身的項目太low時、或者埋怨本身天天在作重複工做時、或者天天對層出不窮的新技術焦頭爛額時,不妨認真的審視下本身的項目,
- 天天重複的工做,是否是能夠本身造輪子了;
- 技術棧太low,是否是能夠平滑過渡到新技術,提升開發效率;
- 學再多的新技術,最終也會迴歸並實踐到項目中。
從工做流程和項目的痛點出發,你會在實踐、總結並解決實際問題中進步的更加迅速。
寫這篇文章的感覺:把這些東西表達出來的難度
>>
文章自己所包含的技術難度