Vue快速實現通用表單驗證的示例程式碼
本文開篇第一句話,想引用魯迅先生《祝福》裡的一句話,那便是:“我真傻,真的,我單單知道後端整天都是CRUD,我沒想到前端整天都是Form表單”。這句話要從哪裡說起呢?大概要從最近半個月的“全棧工程師”說起。專案上需要做一個城市配載的功能,顧名思義,就是通過框選和拖拽的方式在地圖上完成配載。博主選擇了前後端分離的方式,在這個過程中發現:首先,只要有依賴jQuery的元件,譬如Kendoui,即使使用了Vue,依然需要通過jQuery去操作DOM。其次,只有有通過Rozar生成的DOM,譬如HtmlHelper,Vue的雙向繫結就突然變得尷尬起來,更不用說,Rozar中的@語法和Vue中的@指令相互衝突的問題,原本可以直接用v-for生成列表,因為使用了HtmlHelper,突然一下子變得厭惡起來,雖然Rozar語法非常強大,可我依然沒有在JavaScript裡寫C#的熱情,因為實在太痛苦啦Orz……
所以,想做好前後端分離,首先需要分離出一套前端元件庫,做不到這一點,前後端分離就無從談起,就像我們公司的專案,即使框架切換到.NET Core,可是在很長的一段時間裡,我們其實還是再寫MVC,因為所有的元件都是後端提供的HtmlHelper/TagHelper這種形式。我這次做專案的過程中,其實是通過jQuery實現了一部分元件,正因為如此,一個在前後端不分離時非常容易實現的功能,在前後端分離以後發現缺好多東西,就比如最簡單的表單驗證功能,即便你是在做一個新專案,為了保證產品在外觀上的一致性,你還是得依賴老專案的東西,所以,這篇部落格主要想說說前後端分離以後,Vue的時代怎麼去做表單的驗證。因為我不想測試同事再給我提Bug,問我為什麼只有來自後端介面的驗證,而沒有來自前端頁面的驗證。我希望,在寫下這篇部落格之前,我可以實現和老專案一模一樣的表單驗證。如同CRUD之於後端,80%的前端都是在寫Form表單,所以,這個事情還是挺有意思的。
最簡單的表單驗證
OK,作為國內最接“地氣”的前端框架,Vue的文件可以說是相當地“親民”啦!為什麼這樣說呢,因為其實在官方文件中,尤大已經提供了一個表單驗證的示例,這個示例讓我想起給某銀行做自動化工具時的情景,因為這兩者都是採用MVVM的思想,所以,理解起來是非常容易的,即:通過一個列表來儲存錯誤資訊,而這個錯誤資訊會繫結到檢視層,所以,驗證的過程其實就是向這個列表裡新增錯誤資訊的過程。我們一起來看這個例子:
<div> <h2>你好,請登入</h2> <div> <form id="loginFrom"> <div> <label>郵箱</label> <input type="text" class="form-control" id="inputEmail3" placeholder="Email" v-model="email"> </div> </div> <div> <label>密碼</label> <input type="password" class="form-control" id="inputPassword3" placeholder="Password" v-model="password"> </div> <div> <button type="button" class="btn btn-default login" v-on:click="login()">登入</button> </div> <div v-if="errorList.length > 0"> <div class="alert alert-danger" role="alert">{{errorList.join(';')}}</div> </div> </form> </div> </div> <script> var vm = new Vue({ el: '#loginFrom',data: { email: "",password: "",errorList: [] },methods: { validate: function () { this.errorList = [] if (this.email == '') { this.errorList.push('請輸入郵箱'); } else { var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/; if (!reg.test(this.email)) { this.errorList.push('請輸入有效的郵箱'); } } if (this.password == '') { this.errorList.push('請輸入密碼'); } else { if (this.password.length < 6) { this.errorList.push('密碼長度不得少於6位'); } } return this.errorList.length <= 0; },login: function () { if (this.validate()) { alert('登入成功'); } } } }); </script>
為了排除無關內容對大家的影響,寫這個例子的時候,博主排除了一切複雜的HTML結構和CSS樣式,經過簡單潤色以後,這個例子的效果展示如下,果然GUI滿足了人們顏控的一面,可讓這個世界高速執行的是CLI,Bootstrap是博主這種“全棧工程師”的最愛之一。這種驗證方式簡直是人類本能的反應,可這恰好是最糟糕的一個例子,因為這個程式碼完全沒法複用,可以想象得到,如果再繼續增加針對密碼強度,譬如大小寫、數字等等的驗證,這個程式碼會混亂成什麼樣子,所以,這是最簡單的表單驗證,同樣是最糟糕的表單驗證。
基於jQuery的表單驗證
其實,如果不是因為老專案依賴jQuery,而新專案在某些地方又需要和老專案保持一致,有誰會喜歡在Vue的世界裡使用jQuery呢?因為資料驅動和事件驅動,真的是兩種不同的思想,我就見過因為監聽不到某個事件而花費一整天時間的人……所以,這裡使用jQuery的表單驗證外掛jQuery Validation,目的只有一個,即實現博主對自己的承諾,做一個和老專案一模一樣的表單驗證。官方這個示例最大的問題是,它的檢驗邏輯擴充套件性比較差,後端同學對這個應該有所體會啦,譬如實際業務中常常有郵箱、手機號、非空、數字、正則等等的驗證規則,而後端常常採用基於Attribute的驗證或者是FluentValidation這樣的庫,所以,核心問題是,能不能定義相應的驗證規則。接下來,我們通過jQuery的表單驗證外掛來實現驗證。
通常情況下,jQuery Validation支援面向控制元件和麵向程式碼兩種驗證方式。所謂面向控制元件,就是指在控制元件裡新增類似required
、email
、range
等等的擴充套件屬性,jQuery Validation內建了十餘種標準的驗證規則,基本可以滿足我們的日常使用。而面向程式碼,就是通過JavaScript來定義驗證規則,這就非常符合Vue資料驅動的風格了,因為在JavaScript裡一切皆是物件,而這些物件可以作為Vue中的資料來使用。自然而然地,在第一個示例的基礎上,我們可以非常容易地擴展出基於jQuery的表單驗證:
var vm = new Vue({ el:'#loginFrom',data:{ email:"",password:"",validators:{ rules: { email: { required: true,email: true },password: { required: true,minlength: 6,} },messages:{ email:{ required:"請輸入郵箱",email:"請輸入有效的郵箱" },password:{ required:"請輸入密碼",minlength:"密碼長度不得少於6位" } } } },mounted:function(){ $('#loginFrom').validate(this.validators); } });
對於當前表單loginFrom,其驗證規則為validators,它完全參照jQuery Validation
的API文件而來,具體大家可以從jQuery Validation
的文件來做進一步瞭解。這裡唯一看起來不爽的就是#loginFrom
,因為它和整個Vue看起來格格不入。不過,像博主目前專案的處境,如果老專案裡使用jQuery
來對錶單進行驗證,而使用Vue開發的新專案要相容老專案的設計風格,使用jQuery有什麼不可以呢?不得不說,Vue作為一個漸進式的開發框架,真正照顧了各個"年齡"段的前端工程師。使用jQuery Validation
以後的表單驗證效果如下:
通過jQuery Validation
,我們或許能感覺到一點不一樣的地方,那就是表單驗證其實還是蠻有意思的哈。也許是因為我原本是一個無聊的人,所以看到一點新的東西就覺得有趣。就像我雖然在提交資料時在後端做了校驗,可犧牲的其實是整個前端的使用體驗。而如果在前端對資料進行校驗,是在輸入過程中校驗還是在輸入完成校驗,是通過表單自帶的提交功能還是自己發起一個AJAX請求,這裡面的確是有非常多的細節支撐的。第一種方案不支援遠端校驗,這更加能說明校驗本身要考慮的不單單隻有前端了,同理,有了前端的校驗,不代表後端可以不做校驗。前端時間有人在知乎上提問,大意是說前端該不該完全信任後端返回的資料,嚴格來說,我們不應該信任任何人提供的資料,而這就是校驗這件事情本身的意義。
基於Vue的表單驗證
OK,如果說前面的兩種校驗是因為我們有一點歷史包袱,那麼,接下來,我們將嘗試採用更“現代化”的表單驗證方式。通過Vue文件中關於資料校驗這一節的內容,我們瞭解到官方推薦的兩個表單驗證外掛是vuelidate和VeeValidate,而實際上這篇部落格中的第一個例子,就是由文件中的例子演化而來。我個人比較喜歡後者,所以,下面我們將使用這個外掛來完成第三個例子。首先 ,我們通過Vue-Cli
建立一個Vue專案,然後安裝下面vee-validate
和vue-i18n
兩個外掛:
npm install [email protected] --save npm install vue-i18n
注意到這裡指定了版本號,這是因為最新的3.x超出了我這個新人的接受範圍,一句話,太難了!接下來,我們在入口檔案main.js
中新增下面的程式碼,目的是啟用這兩個外掛:
import VueI18n from 'vue-i18n'; import VeeValidate from 'vee-validate'; import zh_CN from 'vee-validate/dist/locale/zh_CN' //啟用Vue國際化外掛 Vue.use(VueI18n) //配置VeeValidate const i18n = new VueI18n({ locale: 'zh_CN',}) Vue.use(VeeValidate,{ i18n,i18nRootKey: 'validation',dictionary: { zh_CN } });
接下來,編寫一個單檔案元件LoginForm.vue
:
<!-- template of LoginForm --> <template> <div class="container"> <h2 class="text-center">你好,請登入</h2> <div class="row"> <form class="form-horizontal col-md-offset-4 col-md-4" id="loginFrom"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">郵箱</label> <div class="col-sm-10"> <input type="text" class="form-control" id="email" name="email" placeholder="Email" v-model="email" v-validate="'required|email'" data-vv-as="郵箱"/> <p class="alert alert-danger" role="alert" v-show="errors.has('email')">{{ errors.first('email') }}</p> </div> </div> <div class="form-group" name="password" rules="required"> <label for="inputPassword3" class="col-sm-2 control-label">密碼</label> <div class="col-sm-10"> <input type="password" class="form-control" id="password" name="password" placeholder="Password" v-model="password" v-validate="'required|min:6'" data-vv-as="密碼"/> <p class="alert alert-danger" role="alert" v-show="errors.has('password')">{{ errors.first('password') }}</p> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <div class="checkbox"> <label> <input type="checkbox" />記住密碼 </label> </div> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="button" class="btn btn-default login" v-on:click="login()">登入</button> </div> </div> </form> </div> </div> </template> <!-- script of LoginForm --> <script> export default { name: "LoginForm",components: {},data: () => ({ email: "",password: "" }),methods: { login: function() { } } }; </script> <!-- style of LoginForm --> <style scoped> .login { color: white; height: 38px; width: 300px; background-color: #2b669a; } </style>
可以看到,我們在關鍵的兩個input控制元件上添加了v-validate
和data-vv-as
這兩個屬性。比如我們這裡需要驗證使用者輸入的郵箱是否合法、郵箱是否為空,那麼我們就可以使用下面的語法:
<input type="text" class="form-control" id="email" name="email" placeholder="Email" v-model="email" v-validate="'required|email'" data-vv-as="郵箱"/> <p class="alert alert-danger" role="alert" v-show="errors.has('email')">{{ errors.first('email') }}</p>
這些語法在Vue中被稱為指令,而data-vv-as
則是HTML5中的一個特性,用來給提示資訊中的欄位起一個別名。實際上,這個外掛裡同樣內建了一批常見的校驗規則。當控制元件中的值不滿足校驗條件時,就會在errors
中產生錯誤資訊,所以,我們根據錯誤資訊中是否包含指定欄位來決定要不要展示錯誤資訊,這就是這個外掛的作用。執行這個例子,我們會得到下面的結果。
既然提到這類表單驗證最難的地方在於擴充套件性,那麼下面我們再來看看如何擴充套件一個新的校驗規則,這裡以最常見的手機號校驗為例,個人以為這是這個外掛最為強大的地方:
Validator.extend('isMobile',{ messages: { zh_CN: field => field + '必須是11位手機號碼' },validate: value => { return value.length === 11 && /^((13|14|15|17|18)[0-9]{1}\d{8})$/.test(value) } })
相信通過今天這篇部落格,大家應該對Vue裡的表單驗證有一點心得了。這類驗證的庫或者框架其實非常多,整合到Vue中要做的工作無外乎寫一個外掛,在控制元件觸發相關事件或者表單提交的時候進行驗證。作為一個Vue的新人,這個過程可謂是路漫漫其修遠。你大概想不到,我是在凌晨加班加到凌晨兩點半的情況下做完這幾個示例的,最近這兩三個月里加的班比我過去三年都多,這到底是好事還是壞事呢?有時候不知道自己還能不能堅持下去,往事已矣,人難免會感到迷茫的吧!
本文小結
這篇部落格主要通過三個示例分享了Vue下表單校驗的實現,而促使博主對這一切進行研究的原始動力,則是源於一個實際工作中通過Vue開發的新專案。前後端要不要分離、專案裡要不要繼續使用jQuery、該不該頻繁地操作DOM,這其實是毫無關聯地三件事情,而這種事情90%的人是完全不關心的,就像有一種看起來相當“成年人”的做法,出了事情第一時間不是去糾結誰的過錯,而是問能不能馬上解決以及解決問題需要多長時間。這看起來好像一點問題都沒有,可不去在意事件本身對錯的人,是因為這些問題不需要他去處理,利益相關和責任相關是完全不一樣的,因為你不能一出問題全部都找到程式設計師這裡,這專案又不是程式設計師一個人的。我關心這些無關緊要的問題,純粹是因為我對自己做的東西有一種感情,我想做好它而已,我希望自己是個純粹的人,而且可以一直純粹下去,晚安!
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。