vue+elementUI 復(fù)雜表單的驗證蜕劝、數(shù)據(jù)提交方案

背景

當我們在做后臺管理系統(tǒng)時檀头,經(jīng)常會遇到非常復(fù)雜的表單:

  • 表單項非常多
  • 在各種表單類型下,顯示不同的表單項
  • 在某些條件下岖沛,某些表單項會關(guān)閉驗證
  • 每個表單項還會有其他自定義邏輯暑始,比如輸入框可以插入模板變量、輸入字符數(shù)量顯示烫止、圖片上傳并顯示蒋荚、富文本。馆蠕。。
  • 在這種錯綜復(fù)雜的情況下惊奇,完成表單的驗證和提交
  • 可以查看具體例子:例子中省略了很多瑣碎的功能互躬,只保留整體的復(fù)雜表單框架,用于展示解決方案

方案1: 在一個vue文件中

所有的表單項顯示隱藏颂郎、驗證吼渡、數(shù)據(jù)獲取、提交乓序、自定義等邏輯放在一起

  • 根據(jù)表單類型寺酪,使用v-if/v-show處理表單項顯示隱藏
  • elementui自定義驗證中坎背,根據(jù)表單類型,判斷表單項是否驗證
  • 根據(jù)表單類型寄雀,獲取不同的數(shù)據(jù)得滤,并提交到不同的接口
  • 其余所有的自定義邏輯

缺點

  • 還是亂
  • 一個vue文件,輕輕松松上2000
  • 在我嘗試加入一種新的表單類型時盒犹,我發(fā)現(xiàn)我已經(jīng)無懂更。從。下急膀。手沮协。

方案2:分離組件

其實很容易想到根據(jù)不同的表單類型,分離出多個相應(yīng)類型的子表單卓嫂。但我在實踐時還是遇到了很多問題:父子表單驗證慷暂、整體提交數(shù)據(jù)的獲取等等,并總結(jié)出一套解決方案:

1. 子組件

所有的子組件中都需要包含兩個方法validate晨雳、getData供父組件調(diào)用呜呐。

(1) validate方法

用于驗證本身組件的表單項,并返回一個promise對象

vaildate() {
    // 返回`elementUI`表單驗證的結(jié)果(為`promise`對象)
    return this.$refs["ruleForm"].validate();
},
    

(2) getData方法

提供子組件中的數(shù)據(jù)

getData() {
    // 返回子組件的form
    return this.ruleForm;
},

2. 父組件

(1) 策略模式

使用策略模式存儲并獲取子表單的ref(用于獲取子表單的方法)和提交函數(shù) 悍募。省略了大量的if-else判斷蘑辑。

data:{
  // type和ref名稱的映射
  typeRefMap: {
      1: "message",
      2: "mail",
      3: "apppush"
  },
  // type和提交函數(shù)的映射。不同類型坠宴,接口可能不同
  typeSubmitMap: {
      1: data => alert(`短信模板創(chuàng)建成功${JSON.stringify(data)}`),
      2: data => alert(`郵件模板創(chuàng)建成功${JSON.stringify(data)}`),
      3: data => alert(`push模板創(chuàng)建成功${JSON.stringify(data)}`)
  },
}

(2) submit方法

用于父子組件表單驗證洋魂、獲取整體數(shù)據(jù)、調(diào)用當前類型提交函數(shù)提交數(shù)據(jù)

因為elementUI表單驗證的validate方法可以返回promise結(jié)果喜鼓,可以利用promise的特性來處理父子表單的驗證副砍。
比如then函數(shù)可以返回另一個promise對象catch可以獲取它以上所有thenreject庄岖、Promise.all豁翎。

  • 父表單驗證通過才會驗證子表單,存在先后順序
    // 父表單驗證通過才會驗證子表單隅忿,存在先后順序
    submitForm() {
        const templateType = this.typeRefMap[this.indexForm.type];
        this.$refs["indexForm"]
        .validate()
        .then(res => {
            // 父表單驗證成功后心剥,驗證子表單
            return this.$refs[templateType].vaildate();
        })
        .then(res => {
            // 全部驗證通過
            // 獲取整體數(shù)據(jù)
            const reqData = {
                // 獲取子組件數(shù)據(jù)
                ...this.$refs[templateType].getData(),
                ...this.indexForm
            };
            // 獲取當前表單類型的提交函數(shù),并提交
            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 => {
          // 都通過時优烧,發(fā)送請求
          const reqData = {
            ...this.$refs[templateType].getData(),
            ...this.indexForm
          };
          this.typeSubmitMap[this.indexForm.type](reqData);
        })
        .catch(err => {
          console.log(err);
        });
    },
    

查看在線項目項目github組件代碼

總結(jié):很多項目我都遇到這種復(fù)雜的表單链峭,也用了很多種解決方案畦娄,在此總結(jié)出了一種比較整潔簡便的方案。當然還有其他很多方案,比如可以把數(shù)據(jù)提交的方法放在每一個子組件中熙卡,公共的表單項數(shù)據(jù)通過props傳遞給子組件用于提交杖刷。有其他更加簡潔的方案,歡迎評論驳癌,或者github上提issue


題外話: 看了前端架構(gòu)師親述:前端工程師成長之路的 N 問 及 回答中的幾個回答后滑燃,對我有很大的啟發(fā)。在對自己的技術(shù)方向喂柒、前景迷茫時不瓶、或者在埋怨自己的項目太low時、或者埋怨自己每天在做重復(fù)工作時灾杰、或者每天對層出不窮的新技術(shù)焦頭爛額時蚊丐,不妨認真的審視下自己的項目

  • 每天重復(fù)的工作艳吠,是不是可以自己造輪子了麦备;
  • 技術(shù)棧太low,是不是可以平滑過渡到新技術(shù)昭娩,提高開發(fā)效率凛篙;
  • 學(xué)再多的新技術(shù),最終也會回歸并實踐到項目中栏渺。

工作流程和項目的痛點出發(fā)呛梆,你會在實踐、總結(jié)并解決實際問題中進步的更加迅速磕诊。


寫這篇文章的感受:把這些東西表達出來的難度 >> 文章本身所包含的技術(shù)難度

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末填物,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子霎终,更是在濱河造成了極大的恐慌滞磺,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莱褒,死亡現(xiàn)場離奇詭異击困,居然都是意外死亡,警方通過查閱死者的電腦和手機广凸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門阅茶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人炮障,你說我怎么就攤上這事目派。” “怎么了胁赢?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我智末,道長谅摄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任系馆,我火速辦了婚禮送漠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘由蘑。我一直安慰自己闽寡,他們只是感情好,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布尼酿。 她就那樣靜靜地躺著爷狈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪裳擎。 梳的紋絲不亂的頭發(fā)上涎永,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機與錄音鹿响,去河邊找鬼羡微。 笑死,一個胖子當著我的面吹牛惶我,可吹牛的內(nèi)容都是我干的妈倔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼绸贡,長吁一口氣:“原來是場噩夢啊……” “哼盯蝴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恃轩,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤结洼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后叉跛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體松忍,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年筷厘,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸣峭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡酥艳,死狀恐怖摊溶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情充石,我是刑警寧澤莫换,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響拉岁,放射性物質(zhì)發(fā)生泄漏坷剧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一喊暖、第九天 我趴在偏房一處隱蔽的房頂上張望惫企。 院中可真熱鬧,春花似錦陵叽、人聲如沸狞尔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽偏序。三九已至,卻和暖如春锌半,著一層夾襖步出監(jiān)牢的瞬間禽车,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工刊殉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留殉摔,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓记焊,卻偏偏與公主長得像逸月,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子遍膜,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容