Vue 兩個字段聯(lián)合校驗之修改密碼功能的實現(xiàn)
1、前言
本文是前文《Vue Element-ui表單校驗規(guī)則,你掌握了哪些?》針對多字段聯(lián)合校驗的典型應(yīng)用。
在修改密碼時,一般需要確認(rèn)兩次密碼一致,涉及2個屬性字段。類似的涉及2個屬性字段的情況有:
- 日期時間范圍,如果兩者都有值,則要求:結(jié)束時間>=開始時間。
- 數(shù)量關(guān)系:數(shù)量下限<=數(shù)量上限。
特點是兩個屬性值都是可變的。本文以校驗兩次密碼的一致性應(yīng)用,給出兩個可變屬性值的字段之間的聯(lián)合校驗的典型解決方案。
2、方案實現(xiàn)
2.1、實現(xiàn)代碼
先給出表單的代碼:
<template>
<div id="contentwrapper">
<h5 class="heading" align=left>用戶管理 / 修改密碼</h5>
<!-- 分隔線 -->
<el-divider></el-divider>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="原 密 碼:" prop="oldPasswd">
<el-input v-model="form.oldPasswd" :type="password">
<!-- input中加圖標(biāo)必須要有slot="suffix"屬性,不然無法顯示圖標(biāo) -->
<i slot="suffix" :class="icon" @click="showPassword"></i>
</el-input>
</el-form-item>
<el-form-item label="新 密 碼:" prop="newPasswd">
<el-input v-model="form.newPasswd" :type="password">
<i slot="suffix" :class="icon" @click="showPassword"></i>
</el-input>
</el-form-item>
<el-form-item label="確認(rèn)密碼:" prop="confirmPasswd">
<el-input v-model="form.confirmPasswd" :type="password">
<i slot="suffix" :class="icon" @click="showPassword"></i>
</el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" style="width:160px" size="small" @click="submit()">確定</el-button>
<el-button type="primary" style="width:160px" size="small" @click="cancel()">取消</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import {passwordValidator} from '@/common/validator.js'
export default {
data() {
// 比較兩次密碼是否相同
const comparePasswdValidator = (rule, value, callback) =>{
// 獲取獲取值的方法
var getvaluesMethod = rule.getValuesMethod;
// 調(diào)用getvaluesMethod方法,獲取對象值
var formData = getvaluesMethod();
// 有一個為空,可能還沒有輸入值,此時不比較
if (formData.newPasswd == '' || formData.confirmPasswd == ''){
return callback();
}
// ===========================================================
// 比較兩次密碼
// 兩個都有值,比較
if (formData.newPasswd == formData.confirmPasswd){
// 新密碼與確認(rèn)密碼一致
// 先清除兩個密碼的校驗告警提示,目前是清除另一個密碼的不一致的提示
this.$refs['form'].clearValidate(['newPasswd','confirmPasswd']);
callback();
}else{
callback(new Error('兩次密碼不一致'));
}
}
return {
form : {
oldPasswd : '',
newPasswd : '',
confirmPasswd : ''
},
//用于改變Input類型
password:"password",
//用于更換Input中的圖標(biāo)
icon:"el-input__icon el-icon-view",
// 校驗規(guī)則配置
rules: {
oldPasswd : [
{required: true, message: "密碼不能為空", trigger: 'blur'}
],
newPasswd : [
{required: true, message: "新密碼不能為空", trigger: 'blur'},
{min: 6, max: 18, message: "新密碼6-18位", trigger: 'blur'},
{validator: passwordValidator, trigger: 'blur'},
{validator: comparePasswdValidator,trigger: 'blur','getValuesMethod':this.getValuesMethod},
],
confirmPasswd : [
{required: true, message: "確認(rèn)密碼不能為空", trigger: 'blur'},
{min: 6, max: 18, message: "確認(rèn)密碼6-18位", trigger: 'blur'},
{validator: passwordValidator, trigger: 'blur'},
{validator: comparePasswdValidator,trigger: 'blur','getValuesMethod':this.getValuesMethod},
],
},
}
},
methods: {
// 獲取值的方法,為所有需要多字段聯(lián)合校驗的校驗器使用
getValuesMethod(){
return this.form;
},
// 密碼的隱藏和顯示
showPassword(){
//點擊圖標(biāo)是密碼隱藏或顯示
if( this.password=="text"){
this.password="password";
//更換圖標(biāo)
this.icon="el-input__icon el-icon-view";
}else {
this.password="text";
this.icon="el-input__icon el-icon-stopwatch";
}
},
// 提交
submit(){
let _this = this;
this.$refs['form'].validate(valid => {
// 驗證通過為true,有一個不通過就是false
if (valid) {
_this.instance.changePasswd(_this.$baseUrl,_this.form).then(res => {
if (res.data.code == _this.global.SucessRequstCode){
// 提示修改成功
alert("重新設(shè)置密碼已成功!");
// 跳轉(zhuǎn)到首頁
this.$router.push({
path: '/home',
});
}else{
if (!_this.commonFuncs.isInterceptorCode(res.data.code)){
alert(res.data.message);
}
}
}).catch(error => {
console.log(error);
});
}
})
},
// 取消
cancel(){
// 跳轉(zhuǎn)到首頁
this.$router.push({
path: '/home',
});
}
}
}
</script>
導(dǎo)入的外部校驗器passwordValidator在/src/common/validator.js文件中,代碼如下:
/* 密碼校驗 */
export function passwordValidator(rule, value, callback) {
const reg =/^[_a-zA-Z0-9@.#%&*!\-\$^]+$/;
if(value == '' || value == undefined || value == null){
callback();
} else {
if (!reg.test(value)){
callback(new Error('密碼由英文字母、數(shù)字以及下列字符組成:@.#%&*!_-$^'));
} else {
callback();
}
}
}
2.2、代碼說明
2.2.1、規(guī)則配置:
// 校驗規(guī)則配置
rules: {
oldPasswd : [
{required: true, message: "密碼不能為空", trigger: 'blur'}
],
newPasswd : [
{required: true, message: "新密碼不能為空", trigger: 'blur'},
{min: 6, max: 18, message: "新密碼6-18位", trigger: 'blur'},
{validator: passwordValidator, trigger: 'blur'},
{validator: comparePasswdValidator,trigger: 'blur','getValuesMethod':this.getValuesMethod},
],
confirmPasswd : [
{required: true, message: "確認(rèn)密碼不能為空", trigger: 'blur'},
{min: 6, max: 18, message: "確認(rèn)密碼6-18位", trigger: 'blur'},
{validator: passwordValidator, trigger: 'blur'},
{validator: comparePasswdValidator,trigger: 'blur','getValuesMethod':this.getValuesMethod},
],
},
重點是newPasswd和confirmPasswd屬性,兩個配置了相同的規(guī)則集,校驗規(guī)則都為:
- 值不能為空。
- 長度為6-18位。
- 符合密碼校驗器passwordValidator的規(guī)則,即密碼由英文字母、數(shù)字以及下列字符組成:@.#%&*!_-$^。
- 比較密碼校驗器comparePasswdValidator,這個校驗器添加了一個自定義屬性getValuesMethod,屬性值為this的getValuesMethod方法,注意是方法,不是方法名。該條規(guī)則,要求methods中有一個getValuesMethod方法,并且實現(xiàn)comparePasswdValidator校驗器。
這些規(guī)則一起作用,所有規(guī)則都通過校驗,屬性校驗才通過,并且檢測次序按照數(shù)組的先后次序執(zhí)行。
校驗規(guī)則中,newPasswd和confirmPasswd屬性,都配置相同的comparePasswdValidator,是因為兩個字段屬性值都是可變的。comparePasswdValidator排在規(guī)則的最后一條,即需要先滿足前面的校驗規(guī)則。
2.2.2、getValuesMethod方法
// 獲取值的方法,為所有需要多字段聯(lián)合校驗的校驗器使用
getValuesMethod(){
return this.form;
},
getValuesMethod方法,返回data中form數(shù)據(jù)對象。這是一個很犀利的操作,相當(dāng)于提供了全局的數(shù)據(jù)探針,可以在校驗器中訪問data的form數(shù)據(jù)對象,并且由于form的v-modal模型,確保數(shù)據(jù)的實時性,即無需擔(dān)心獲取不到其它屬性的最新取值。getValuesMethod方法,提供了數(shù)據(jù)綁定的另類思路。
2.2.3、comparePasswdValidator校驗器
// 比較兩次密碼是否相同
const comparePasswdValidator = (rule, value, callback) =>{
// 獲取獲取值的方法
var getvaluesMethod = rule.getValuesMethod;
// 調(diào)用getvaluesMethod方法,獲取對象值
var formData = getvaluesMethod();
// 有一個為空,可能還沒有輸入值,此時不比較
if (formData.newPasswd == '' || formData.confirmPasswd == ''){
return callback();
}
// ===========================================================
// 比較兩次密碼
// 兩個都有值,比較
if (formData.newPasswd == formData.confirmPasswd){
// 新密碼與確認(rèn)密碼一致
// 先清除兩個密碼的校驗告警提示,目前是清除另一個密碼的不一致的提示
this.$refs['form'].clearValidate(['newPasswd','confirmPasswd']);
callback();
}else{
callback(new Error('兩次密碼不一致'));
}
}
因為配置的自定義規(guī)則屬性'getValuesMethod'是一個指向this.getValuesMethod的方法,因此該屬性可以看作方法來調(diào)用:
// 獲取獲取值的方法
var getvaluesMethod = rule.getValuesMethod;
// 調(diào)用getvaluesMethod方法,獲取對象值
var formData = getvaluesMethod();
方法屬性的調(diào)用結(jié)果,返回了指向this.form的數(shù)據(jù)對象,于是就可以隨意訪問該對象的屬性。
在比較兩者之前,如果發(fā)現(xiàn)有一者為空,則返回。因為當(dāng)前屬性輸入值之后,對端屬性可能還沒有輸入值,此時不應(yīng)該比較。
// 有一個為空,可能還沒有輸入值,此時不比較
if (formData.newPasswd == '' || formData.confirmPasswd == ''){
return callback();
}
兩次密碼比較:
// ===========================================================
// 比較兩次密碼
// 兩個都有值,比較
if (formData.newPasswd == formData.confirmPasswd){
// 新密碼與確認(rèn)密碼一致
// 先清除兩個密碼的校驗告警提示,目前是清除另一個密碼的不一致的提示
this.$refs['form'].clearValidate(['newPasswd','confirmPasswd']);
callback();
}else{
callback(new Error('兩次密碼不一致'));
}
兩次密碼比較,如果兩個密碼一致,就輸出告警提示。如果一致,則需要先清除對端的告警提示,因為此時對端可能有”兩次密碼不一致“的提示。
// 先清除兩個密碼的校驗告警提示,目前是清除另一個密碼的不一致的提示
this.$refs['form'].clearValidate(['newPasswd','confirmPasswd']);
clearValidate方法,是element-form的方法,作用是清除一個或多個校驗規(guī)則屬性的異常提示。
這時,是否會發(fā)生”誤殺“情況呢?即清除操作將對端的其它異常提示也清除了??紤]到此時兩次密碼相同,且兩者校驗規(guī)則是相同的,由于此校驗規(guī)則排在最后,從檢測次序來說,是最后執(zhí)行的,也就是說,執(zhí)行到本校驗器時,其它校驗都通過了。因此,這種”誤殺“的情況不會發(fā)生。實際執(zhí)行效果也是如此。
另外,需要注意的,此時不能用下列代碼代替上面clearValidate調(diào)用語句:
// 執(zhí)行對端的校驗
if (rule.field == 'newPasswd')
{
// 如果當(dāng)前屬性為newPasswd
this.$refs['form'].validateField('confirmPasswd');
}else{
this.$refs['form'].validateField('newPasswd');
}
因為,此時正在執(zhí)行校驗,再調(diào)用對端校驗,會導(dǎo)致對端調(diào)用comparePasswdValidator,而對端校驗結(jié)果發(fā)現(xiàn)兩次密碼一致,將再次調(diào)用對端(對端的對端,即本身)校驗,于是死循環(huán)了,導(dǎo)致調(diào)用堆棧溢出。因此,校驗器代碼中,盡量不要再調(diào)用validateField方法。
2.3、校驗效果
下面是一些效果圖:
初始狀態(tài):

修改確認(rèn)密碼,離開輸入焦點:

進(jìn)入新密碼輸入框,不輸入,離開輸入焦點:

修改確認(rèn)密碼,刪除尾部的字符"8",離開輸入焦點,此時又回到了初始狀態(tài)。
到此這篇關(guān)于Vue 兩個字段聯(lián)合校驗典型例子--修改密碼的文章就介紹到這了,更多相關(guān)Vue修改密碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue中scrollIntoView()方法詳解與實際運(yùn)用舉例
這篇文章主要給大家介紹了關(guān)于Vue中scrollIntoView()方法詳解與實際運(yùn)用舉例的相關(guān)資料,該scrollIntoView()方法將調(diào)用它的元素滾動到瀏覽器窗口的可見區(qū)域,需要的朋友可以參考下2023-12-12
vue-以文件流-blob-的形式-下載-導(dǎo)出文件操作
這篇文章主要介紹了vue-以文件流-blob-的形式-下載-導(dǎo)出文件操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
webpack+vue.js構(gòu)建前端工程化的詳細(xì)教程
這篇文章主要介紹了webpack+vue.js構(gòu)建前端工程化的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05

