Vue 兩個字段聯合校驗之修改密碼功能的實現
1、前言
本文是前文《Vue Element-ui表單校驗規則,你掌握瞭哪些?》針對多字段聯合校驗的典型應用。
在修改密碼時,一般需要確認兩次密碼一致,涉及2個屬性字段。類似的涉及2個屬性字段的情況有:
- 日期時間范圍,如果兩者都有值,則要求:結束時間>=開始時間。
- 數量關系:數量下限<=數量上限。
特點是兩個屬性值都是可變的。本文以校驗兩次密碼的一致性應用,給出兩個可變屬性值的字段之間的聯合校驗的典型解決方案。
2、方案實現
2.1、實現代碼
先給出表單的代碼:
<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中加圖標必須要有slot="suffix"屬性,不然無法顯示圖標 --> <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="確認密碼:" 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; // 調用getvaluesMethod方法,獲取對象值 var formData = getvaluesMethod(); // 有一個為空,可能還沒有輸入值,此時不比較 if (formData.newPasswd == '' || formData.confirmPasswd == ''){ return callback(); } // =========================================================== // 比較兩次密碼 // 兩個都有值,比較 if (formData.newPasswd == formData.confirmPasswd){ // 新密碼與確認密碼一致 // 先清除兩個密碼的校驗告警提示,目前是清除另一個密碼的不一致的提示 this.$refs['form'].clearValidate(['newPasswd','confirmPasswd']); callback(); }else{ callback(new Error('兩次密碼不一致')); } } return { form : { oldPasswd : '', newPasswd : '', confirmPasswd : '' }, //用於改變Input類型 password:"password", //用於更換Input中的圖標 icon:"el-input__icon el-icon-view", // 校驗規則配置 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: "確認密碼不能為空", trigger: 'blur'}, {min: 6, max: 18, message: "確認密碼6-18位", trigger: 'blur'}, {validator: passwordValidator, trigger: 'blur'}, {validator: comparePasswdValidator,trigger: 'blur','getValuesMethod':this.getValuesMethod}, ], }, } }, methods: { // 獲取值的方法,為所有需要多字段聯合校驗的校驗器使用 getValuesMethod(){ return this.form; }, // 密碼的隱藏和顯示 showPassword(){ //點擊圖標是密碼隱藏或顯示 if( this.password=="text"){ this.password="password"; //更換圖標 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("重新設置密碼已成功!"); // 跳轉到首頁 this.$router.push({ path: '/home', }); }else{ if (!_this.commonFuncs.isInterceptorCode(res.data.code)){ alert(res.data.message); } } }).catch(error => { console.log(error); }); } }) }, // 取消 cancel(){ // 跳轉到首頁 this.$router.push({ path: '/home', }); } } } </script>
導入的外部校驗器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('密碼由英文字母、數字以及下列字符組成:@.#%&*!_-$^')); } else { callback(); } } }
2.2、代碼說明
2.2.1、規則配置:
// 校驗規則配置 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: "確認密碼不能為空", trigger: 'blur'}, {min: 6, max: 18, message: "確認密碼6-18位", trigger: 'blur'}, {validator: passwordValidator, trigger: 'blur'}, {validator: comparePasswdValidator,trigger: 'blur','getValuesMethod':this.getValuesMethod}, ], },
重點是newPasswd和confirmPasswd屬性,兩個配置瞭相同的規則集,校驗規則都為:
- 值不能為空。
- 長度為6-18位。
- 符合密碼校驗器passwordValidator的規則,即密碼由英文字母、數字以及下列字符組成:@.#%&*!_-$^。
- 比較密碼校驗器comparePasswdValidator,這個校驗器添加瞭一個自定義屬性getValuesMethod,屬性值為this的getValuesMethod方法,註意是方法,不是方法名。該條規則,要求methods中有一個getValuesMethod方法,並且實現comparePasswdValidator校驗器。
這些規則一起作用,所有規則都通過校驗,屬性校驗才通過,並且檢測次序按照數組的先後次序執行。
校驗規則中,newPasswd和confirmPasswd屬性,都配置相同的comparePasswdValidator,是因為兩個字段屬性值都是可變的。comparePasswdValidator排在規則的最後一條,即需要先滿足前面的校驗規則。
2.2.2、getValuesMethod方法
// 獲取值的方法,為所有需要多字段聯合校驗的校驗器使用 getValuesMethod(){ return this.form; },
getValuesMethod方法,返回data中form數據對象。這是一個很犀利的操作,相當於提供瞭全局的數據探針,可以在校驗器中訪問data的form數據對象,並且由於form的v-modal模型,確保數據的實時性,即無需擔心獲取不到其它屬性的最新取值。getValuesMethod方法,提供瞭數據綁定的另類思路。
2.2.3、comparePasswdValidator校驗器
// 比較兩次密碼是否相同 const comparePasswdValidator = (rule, value, callback) =>{ // 獲取獲取值的方法 var getvaluesMethod = rule.getValuesMethod; // 調用getvaluesMethod方法,獲取對象值 var formData = getvaluesMethod(); // 有一個為空,可能還沒有輸入值,此時不比較 if (formData.newPasswd == '' || formData.confirmPasswd == ''){ return callback(); } // =========================================================== // 比較兩次密碼 // 兩個都有值,比較 if (formData.newPasswd == formData.confirmPasswd){ // 新密碼與確認密碼一致 // 先清除兩個密碼的校驗告警提示,目前是清除另一個密碼的不一致的提示 this.$refs['form'].clearValidate(['newPasswd','confirmPasswd']); callback(); }else{ callback(new Error('兩次密碼不一致')); } }
因為配置的自定義規則屬性’getValuesMethod’是一個指向this.getValuesMethod的方法,因此該屬性可以看作方法來調用:
// 獲取獲取值的方法 var getvaluesMethod = rule.getValuesMethod; // 調用getvaluesMethod方法,獲取對象值 var formData = getvaluesMethod();
方法屬性的調用結果,返回瞭指向this.form的數據對象,於是就可以隨意訪問該對象的屬性。
在比較兩者之前,如果發現有一者為空,則返回。因為當前屬性輸入值之後,對端屬性可能還沒有輸入值,此時不應該比較。
// 有一個為空,可能還沒有輸入值,此時不比較 if (formData.newPasswd == '' || formData.confirmPasswd == ''){ return callback(); }
兩次密碼比較:
// =========================================================== // 比較兩次密碼 // 兩個都有值,比較 if (formData.newPasswd == formData.confirmPasswd){ // 新密碼與確認密碼一致 // 先清除兩個密碼的校驗告警提示,目前是清除另一個密碼的不一致的提示 this.$refs['form'].clearValidate(['newPasswd','confirmPasswd']); callback(); }else{ callback(new Error('兩次密碼不一致')); }
兩次密碼比較,如果兩個密碼一致,就輸出告警提示。如果一致,則需要先清除對端的告警提示,因為此時對端可能有”兩次密碼不一致“的提示。
// 先清除兩個密碼的校驗告警提示,目前是清除另一個密碼的不一致的提示 this.$refs['form'].clearValidate(['newPasswd','confirmPasswd']);
clearValidate方法,是element-form的方法,作用是清除一個或多個校驗規則屬性的異常提示。
這時,是否會發生”誤殺“情況呢?即清除操作將對端的其它異常提示也清除瞭。考慮到此時兩次密碼相同,且兩者校驗規則是相同的,由於此校驗規則排在最後,從檢測次序來說,是最後執行的,也就是說,執行到本校驗器時,其它校驗都通過瞭。因此,這種”誤殺“的情況不會發生。實際執行效果也是如此。
另外,需要註意的,此時不能用下列代碼代替上面clearValidate調用語句:
// 執行對端的校驗 if (rule.field == 'newPasswd') { // 如果當前屬性為newPasswd this.$refs['form'].validateField('confirmPasswd'); }else{ this.$refs['form'].validateField('newPasswd'); }
因為,此時正在執行校驗,再調用對端校驗,會導致對端調用comparePasswdValidator,而對端校驗結果發現兩次密碼一致,將再次調用對端(對端的對端,即本身)校驗,於是死循環瞭,導致調用堆棧溢出。因此,校驗器代碼中,盡量不要再調用validateField方法。
2.3、校驗效果
下面是一些效果圖:
初始狀態:
修改確認密碼,離開輸入焦點:
進入新密碼輸入框,不輸入,離開輸入焦點:
修改確認密碼,刪除尾部的字符”8″,離開輸入焦點,此時又回到瞭初始狀態。
到此這篇關於Vue 兩個字段聯合校驗典型例子–修改密碼的文章就介紹到這瞭,更多相關Vue修改密碼內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- validate 註冊頁的表單數據校驗實現詳解
- Vue Element-ui表單校驗規則實現
- Vue使用antd中input組件去驗證輸入框輸入內容(rules 案例)
- antd vue v-decorator的取值與賦值問題
- vue表單驗證rules及validator驗證器的使用方法實例