Vue快速實(shí)現(xiàn)通用表單驗(yàn)證的示例代碼
本文開(kāi)篇第一句話,想引用魯迅先生《祝福》里的一句話,那便是:“我真傻,真的,我單單知道后端整天都是CRUD,我沒(méi)想到前端整天都是Form表單”。這句話要從哪里說(shuō)起呢?大概要從最近半個(gè)月的“全棧工程師”說(shuō)起。項(xiàng)目上需要做一個(gè)城市配載的功能,顧名思義,就是通過(guò)框選和拖拽的方式在地圖上完成配載。博主選擇了前后端分離的方式,在這個(gè)過(guò)程中發(fā)現(xiàn):首先,只要有依賴(lài)jQuery的組件,譬如Kendoui,即使使用了Vue,依然需要通過(guò)jQuery去操作DOM。其次,只有有通過(guò)Rozar生成的DOM,譬如HtmlHelper,Vue的雙向綁定就突然變得尷尬起來(lái),更不用說(shuō),Rozar中的@語(yǔ)法和Vue中的@指令相互沖突的問(wèn)題,原本可以直接用v-for生成列表,因?yàn)槭褂昧薍tmlHelper,突然一下子變得厭惡起來(lái),雖然Rozar語(yǔ)法非常強(qiáng)大,可我依然沒(méi)有在JavaScript里寫(xiě)C#的熱情,因?yàn)閷?shí)在太痛苦啦Orz……
所以,想做好前后端分離,首先需要分離出一套前端組件庫(kù),做不到這一點(diǎn),前后端分離就無(wú)從談起,就像我們公司的項(xiàng)目,即使框架切換到.NET Core,可是在很長(zhǎng)的一段時(shí)間里,我們其實(shí)還是再寫(xiě)MVC,因?yàn)樗械慕M件都是后端提供的HtmlHelper/TagHelper這種形式。我這次做項(xiàng)目的過(guò)程中,其實(shí)是通過(guò)jQuery實(shí)現(xiàn)了一部分組件,正因?yàn)槿绱耍粋€(gè)在前后端不分離時(shí)非常容易實(shí)現(xiàn)的功能,在前后端分離以后發(fā)現(xiàn)缺好多東西,就比如最簡(jiǎn)單的表單驗(yàn)證功能,即便你是在做一個(gè)新項(xiàng)目,為了保證產(chǎn)品在外觀上的一致性,你還是得依賴(lài)?yán)享?xiàng)目的東西,所以,這篇博客主要想說(shuō)說(shuō)前后端分離以后,Vue的時(shí)代怎么去做表單的驗(yàn)證。因?yàn)槲也幌霚y(cè)試同事再給我提Bug,問(wèn)我為什么只有來(lái)自后端接口的驗(yàn)證,而沒(méi)有來(lái)自前端頁(yè)面的驗(yàn)證。我希望,在寫(xiě)下這篇博客之前,我可以實(shí)現(xiàn)和老項(xiàng)目一模一樣的表單驗(yàn)證。如同CRUD之于后端,80%的前端都是在寫(xiě)Form表單,所以,這個(gè)事情還是挺有意思的。
最簡(jiǎn)單的表單驗(yàn)證
OK,作為國(guó)內(nèi)最接“地氣”的前端框架,Vue的文檔可以說(shuō)是相當(dāng)?shù)亍坝H民”啦!為什么這樣說(shuō)呢,因?yàn)槠鋵?shí)在官方文檔中,尤大已經(jīng)提供了一個(gè)表單驗(yàn)證的示例,這個(gè)示例讓我想起給某銀行做自動(dòng)化工具時(shí)的情景,因?yàn)檫@兩者都是采用MVVM的思想,所以,理解起來(lái)是非常容易的,即:通過(guò)一個(gè)列表來(lái)存儲(chǔ)錯(cuò)誤信息,而這個(gè)錯(cuò)誤信息會(huì)綁定到視圖層,所以,驗(yàn)證的過(guò)程其實(shí)就是向這個(gè)列表里添加錯(cuò)誤信息的過(guò)程。我們一起來(lái)看這個(gè)例子:
<div>
<h2>你好,請(qǐng)登錄</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('請(qǐng)輸入郵箱');
} 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('請(qǐng)輸入有效的郵箱');
}
}
if (this.password == '') {
this.errorList.push('請(qǐng)輸入密碼');
} else {
if (this.password.length < 6) {
this.errorList.push('密碼長(zhǎng)度不得少于6位');
}
}
return this.errorList.length <= 0;
},
login: function () {
if (this.validate()) {
alert('登錄成功');
}
}
}
});
</script>
為了排除無(wú)關(guān)內(nèi)容對(duì)大家的影響,寫(xiě)這個(gè)例子的時(shí)候,博主排除了一切復(fù)雜的HTML結(jié)構(gòu)和CSS樣式,經(jīng)過(guò)簡(jiǎn)單潤(rùn)色以后,這個(gè)例子的效果展示如下,果然GUI滿(mǎn)足了人們顏控的一面,可讓這個(gè)世界高速運(yùn)行的是CLI,Bootstrap是博主這種“全棧工程師”的最?lèi)?ài)之一。這種驗(yàn)證方式簡(jiǎn)直是人類(lèi)本能的反應(yīng),可這恰好是最糟糕的一個(gè)例子,因?yàn)檫@個(gè)代碼完全沒(méi)法復(fù)用,可以想象得到,如果再繼續(xù)增加針對(duì)密碼強(qiáng)度,譬如大小寫(xiě)、數(shù)字等等的驗(yàn)證,這個(gè)代碼會(huì)混亂成什么樣子,所以,這是最簡(jiǎn)單的表單驗(yàn)證,同樣是最糟糕的表單驗(yàn)證。

基于jQuery的表單驗(yàn)證
其實(shí),如果不是因?yàn)槔享?xiàng)目依賴(lài)jQuery,而新項(xiàng)目在某些地方又需要和老項(xiàng)目保持一致,有誰(shuí)會(huì)喜歡在Vue的世界里使用jQuery呢?因?yàn)閿?shù)據(jù)驅(qū)動(dòng)和事件驅(qū)動(dòng),真的是兩種不同的思想,我就見(jiàn)過(guò)因?yàn)楸O(jiān)聽(tīng)不到某個(gè)事件而花費(fèi)一整天時(shí)間的人……所以,這里使用jQuery的表單驗(yàn)證插件jQuery Validation,目的只有一個(gè),即實(shí)現(xiàn)博主對(duì)自己的承諾,做一個(gè)和老項(xiàng)目一模一樣的表單驗(yàn)證。官方這個(gè)示例最大的問(wèn)題是,它的檢驗(yàn)邏輯擴(kuò)展性比較差,后端同學(xué)對(duì)這個(gè)應(yīng)該有所體會(huì)啦,譬如實(shí)際業(yè)務(wù)中常常有郵箱、手機(jī)號(hào)、非空、數(shù)字、正則等等的驗(yàn)證規(guī)則,而后端常常采用基于Attribute的驗(yàn)證或者是FluentValidation這樣的庫(kù),所以,核心問(wèn)題是,能不能定義相應(yīng)的驗(yàn)證規(guī)則。接下來(lái),我們通過(guò)jQuery的表單驗(yàn)證插件來(lái)實(shí)現(xiàn)驗(yàn)證。
通常情況下,jQuery Validation支持面向控件和面向代碼兩種驗(yàn)證方式。所謂面向控件,就是指在控件里添加類(lèi)似required、email、range等等的擴(kuò)展屬性,jQuery Validation內(nèi)置了十余種標(biāo)準(zhǔn)的驗(yàn)證規(guī)則,基本可以滿(mǎn)足我們的日常使用。而面向代碼,就是通過(guò)JavaScript來(lái)定義驗(yàn)證規(guī)則,這就非常符合Vue數(shù)據(jù)驅(qū)動(dòng)的風(fēng)格了,因?yàn)樵贘avaScript里一切皆是對(duì)象,而這些對(duì)象可以作為Vue中的數(shù)據(jù)來(lái)使用。自然而然地,在第一個(gè)示例的基礎(chǔ)上,我們可以非常容易地?cái)U(kuò)展出基于jQuery的表單驗(yàn)證:
var vm = new Vue({
el:'#loginFrom',
data:{
email:"",
password:"",
validators:{
rules: {
email: {
required: true,
email: true
},
password: {
required: true,
minlength: 6,
}
},
messages:{
email:{
required:"請(qǐng)輸入郵箱",
email:"請(qǐng)輸入有效的郵箱"
},
password:{
required:"請(qǐng)輸入密碼",
minlength:"密碼長(zhǎng)度不得少于6位"
}
}
}
},
mounted:function(){
$('#loginFrom').validate(this.validators);
}
});
對(duì)于當(dāng)前表單loginFrom,其驗(yàn)證規(guī)則為validators,它完全參照jQuery Validation的API文檔而來(lái),具體大家可以從jQuery Validation的文檔來(lái)做進(jìn)一步了解。這里唯一看起來(lái)不爽的就是#loginFrom,因?yàn)樗驼麄€(gè)Vue看起來(lái)格格不入。不過(guò),像博主目前項(xiàng)目的處境,如果老項(xiàng)目里使用jQuery來(lái)對(duì)表單進(jìn)行驗(yàn)證,而使用Vue開(kāi)發(fā)的新項(xiàng)目要兼容老項(xiàng)目的設(shè)計(jì)風(fēng)格,使用jQuery有什么不可以呢?不得不說(shuō),Vue作為一個(gè)漸進(jìn)式的開(kāi)發(fā)框架,真正照顧了各個(gè)"年齡"段的前端工程師。使用jQuery Validation以后的表單驗(yàn)證效果如下:

通過(guò)jQuery Validation,我們或許能感覺(jué)到一點(diǎn)不一樣的地方,那就是表單驗(yàn)證其實(shí)還是蠻有意思的哈。也許是因?yàn)槲以臼且粋€(gè)無(wú)聊的人,所以看到一點(diǎn)新的東西就覺(jué)得有趣。就像我雖然在提交數(shù)據(jù)時(shí)在后端做了校驗(yàn),可犧牲的其實(shí)是整個(gè)前端的使用體驗(yàn)。而如果在前端對(duì)數(shù)據(jù)進(jìn)行校驗(yàn),是在輸入過(guò)程中校驗(yàn)還是在輸入完成校驗(yàn),是通過(guò)表單自帶的提交功能還是自己發(fā)起一個(gè)AJAX請(qǐng)求,這里面的確是有非常多的細(xì)節(jié)支撐的。第一種方案不支持遠(yuǎn)程校驗(yàn),這更加能說(shuō)明校驗(yàn)本身要考慮的不單單只有前端了,同理,有了前端的校驗(yàn),不代表后端可以不做校驗(yàn)。前端時(shí)間有人在知乎上提問(wèn),大意是說(shuō)前端該不該完全信任后端返回的數(shù)據(jù),嚴(yán)格來(lái)說(shuō),我們不應(yīng)該信任任何人提供的數(shù)據(jù),而這就是校驗(yàn)這件事情本身的意義。
基于Vue的表單驗(yàn)證
OK,如果說(shuō)前面的兩種校驗(yàn)是因?yàn)槲覀冇幸稽c(diǎn)歷史包袱,那么,接下來(lái),我們將嘗試采用更“現(xiàn)代化”的表單驗(yàn)證方式。通過(guò)Vue文檔中關(guān)于數(shù)據(jù)校驗(yàn)這一節(jié)的內(nèi)容,我們了解到官方推薦的兩個(gè)表單驗(yàn)證插件是vuelidate和VeeValidate,而實(shí)際上這篇博客中的第一個(gè)例子,就是由文檔中的例子演化而來(lái)。我個(gè)人比較喜歡后者,所以,下面我們將使用這個(gè)插件來(lái)完成第三個(gè)例子。首先 ,我們通過(guò)Vue-Cli創(chuàng)建一個(gè)Vue項(xiàng)目,然后安裝下面vee-validate和vue-i18n兩個(gè)插件:
npm install vee-validate@2.0.0 --save npm install vue-i18n
注意到這里指定了版本號(hào),這是因?yàn)樽钚碌?.x超出了我這個(gè)新人的接受范圍,一句話,太難了!接下來(lái),我們?cè)谌肟谖募?code>main.js中添加下面的代碼,目的是啟用這兩個(gè)插件:
import VueI18n from 'vue-i18n';
import VeeValidate from 'vee-validate';
import zh_CN from 'vee-validate/dist/locale/zh_CN'
//啟用Vue國(guó)際化插件
Vue.use(VueI18n)
//配置VeeValidate
const i18n = new VueI18n({
locale: 'zh_CN',
})
Vue.use(VeeValidate, {
i18n,
i18nRootKey: 'validation',
dictionary: {
zh_CN
}
});
接下來(lái),編寫(xiě)一個(gè)單文件組件LoginForm.vue:
<!-- template of LoginForm -->
<template>
<div class="container">
<h2 class="text-center">你好,請(qǐng)登錄</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>
可以看到,我們?cè)陉P(guān)鍵的兩個(gè)input控件上添加了v-validate和data-vv-as這兩個(gè)屬性。比如我們這里需要驗(yàn)證用戶(hù)輸入的郵箱是否合法、郵箱是否為空,那么我們就可以使用下面的語(yǔ)法:
<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>
這些語(yǔ)法在Vue中被稱(chēng)為指令,而data-vv-as則是HTML5中的一個(gè)特性,用來(lái)給提示信息中的字段起一個(gè)別名。實(shí)際上,這個(gè)插件里同樣內(nèi)置了一批常見(jiàn)的校驗(yàn)規(guī)則。當(dāng)控件中的值不滿(mǎn)足校驗(yàn)條件時(shí),就會(huì)在errors中產(chǎn)生錯(cuò)誤信息,所以,我們根據(jù)錯(cuò)誤信息中是否包含指定字段來(lái)決定要不要展示錯(cuò)誤信息,這就是這個(gè)插件的作用。運(yùn)行這個(gè)例子,我們會(huì)得到下面的結(jié)果。

既然提到這類(lèi)表單驗(yàn)證最難的地方在于擴(kuò)展性,那么下面我們?cè)賮?lái)看看如何擴(kuò)展一個(gè)新的校驗(yàn)規(guī)則,這里以最常見(jiàn)的手機(jī)號(hào)校驗(yàn)為例, 個(gè)人以為這是這個(gè)插件最為強(qiáng)大的地方:
Validator.extend('isMobile', {
messages: {
zh_CN: field => field + '必須是11位手機(jī)號(hào)碼'
},
validate: value => {
return value.length === 11 && /^((13|14|15|17|18)[0-9]{1}\d{8})$/.test(value)
}
})
相信通過(guò)今天這篇博客,大家應(yīng)該對(duì)Vue里的表單驗(yàn)證有一點(diǎn)心得了。這類(lèi)驗(yàn)證的庫(kù)或者框架其實(shí)非常多,整合到Vue中要做的工作無(wú)外乎寫(xiě)一個(gè)插件,在控件觸發(fā)相關(guān)事件或者表單提交的時(shí)候進(jìn)行驗(yàn)證。作為一個(gè)Vue的新人,這個(gè)過(guò)程可謂是路漫漫其修遠(yuǎn)。你大概想不到,我是在凌晨加班加到凌晨?jī)牲c(diǎn)半的情況下做完這幾個(gè)示例的,最近這兩三個(gè)月里加的班比我過(guò)去三年都多,這到底是好事還是壞事呢?有時(shí)候不知道自己還能不能堅(jiān)持下去,往事已矣,人難免會(huì)感到迷茫的吧!
本文小結(jié)
這篇博客主要通過(guò)三個(gè)示例分享了Vue下表單校驗(yàn)的實(shí)現(xiàn),而促使博主對(duì)這一切進(jìn)行研究的原始動(dòng)力,則是源于一個(gè)實(shí)際工作中通過(guò)Vue開(kāi)發(fā)的新項(xiàng)目。前后端要不要分離、項(xiàng)目里要不要繼續(xù)使用jQuery、該不該頻繁地操作DOM,這其實(shí)是毫無(wú)關(guān)聯(lián)地三件事情,而這種事情90%的人是完全不關(guān)心的,就像有一種看起來(lái)相當(dāng)“成年人”的做法,出了事情第一時(shí)間不是去糾結(jié)誰(shuí)的過(guò)錯(cuò),而是問(wèn)能不能馬上解決以及解決問(wèn)題需要多長(zhǎng)時(shí)間。這看起來(lái)好像一點(diǎn)問(wèn)題都沒(méi)有,可不去在意事件本身對(duì)錯(cuò)的人,是因?yàn)檫@些問(wèn)題不需要他去處理,利益相關(guān)和責(zé)任相關(guān)是完全不一樣的,因?yàn)槟悴荒芤怀鰡?wèn)題全部都找到程序員這里,這項(xiàng)目又不是程序員一個(gè)人的。我關(guān)心這些無(wú)關(guān)緊要的問(wèn)題,純粹是因?yàn)槲覍?duì)自己做的東西有一種感情,我想做好它而已,我希望自己是個(gè)純粹的人,而且可以一直純粹下去,晚安!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Vue表單驗(yàn)證插件Vue Validator使用方法詳解
- Vue ElementUI之Form表單驗(yàn)證遇到的問(wèn)題
- vue表單驗(yàn)證你真的會(huì)了嗎?vue表單驗(yàn)證(form)validate
- element 結(jié)合vue 在表單驗(yàn)證時(shí)有值卻提示錯(cuò)誤的解決辦法
- Vue中使用vee-validate表單驗(yàn)證的方法
- Vue表單驗(yàn)證插件的制作過(guò)程
- vue動(dòng)態(tài)綁定組件子父組件多表單驗(yàn)證功能的實(shí)現(xiàn)代碼
- vue+vue-validator 表單驗(yàn)證功能的實(shí)現(xiàn)代碼
- Vue from-validate 表單驗(yàn)證的示例代碼
- vee-validate vue 2.0自定義表單驗(yàn)證的實(shí)例
- Vue循環(huán)組件加validate多表單驗(yàn)證的實(shí)例
相關(guān)文章
關(guān)于Vue?CLI3中啟動(dòng)cli服務(wù)參數(shù)說(shuō)明
這篇文章主要介紹了關(guān)于Vue?CLI3中啟動(dòng)cli服務(wù)參數(shù)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
vue實(shí)現(xiàn)tagsview多頁(yè)簽導(dǎo)航功能的示例代碼
這篇文章主要介紹了vue實(shí)現(xiàn)tagsview多頁(yè)簽導(dǎo)航功能,本文梳理了一下vue-element-admin項(xiàng)目實(shí)現(xiàn)多頁(yè)簽功能的整體步驟,需要的朋友可以參考下2022-08-08
Vue 按照創(chuàng)建時(shí)間和當(dāng)前時(shí)間顯示操作(剛剛,幾小時(shí)前,幾天前)
這篇文章主要介紹了Vue 按照創(chuàng)建時(shí)間和當(dāng)前時(shí)間顯示操作(剛剛,幾小時(shí)前,幾天前),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
vue-cli2.x舊版本卸載不掉的問(wèn)題踩坑指南(附Vue腳手架安裝教程)
遇到一個(gè)Vuecli2腳手架卸載不了的問(wèn)題,查了許多資料說(shuō)的都比較復(fù)雜,所以下面這篇文章主要給大家介紹了關(guān)于vue-cli2.x舊版本卸載不掉的問(wèn)題踩坑的相關(guān)資料,文中還附了Vue腳手架安裝教程,需要的朋友可以參考下2022-07-07
vue中如何使用elementUI表格動(dòng)態(tài)行合并
這篇文章主要介紹了vue中如何使用elementUI表格動(dòng)態(tài)行合并,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
使用寶塔面板中Nginx部署前端Vue項(xiàng)目完整步驟
在Kubernetes(K8S)部署前端Vue項(xiàng)目通常會(huì)涉及到使用Nginx作為靜態(tài)資源服務(wù)器的一個(gè)重要部分,這篇文章主要給大家介紹了關(guān)于使用寶塔面板中Nginx部署前端Vue項(xiàng)目的相關(guān)資料,需要的朋友可以參考下2024-10-10

