文章目錄
前言
最近在做項目過程中,測試組人員對添加表單中的身份信息提出了需求,在填寫身份證信息時,希望能對所填信息進行合法性校驗。比如身份證的位數(目前二代身份證都是18位)、地區編號(所在省(市,旗,區)的行政區代碼)、出生年月日(月份所對應的28天/29天/30天/31天)、順序碼(第十五到十七位,第十七位奇數是男性,偶數是女性),校驗碼(第十八位,如果尾號是10就用X代替了)。
正文
有了新需求,就要滿足用戶的要求。接下來將介紹我是如何實現身份校驗的。項目中使用的前端框架位vue,組件庫爲Element ui。
1、 首先,根據實際情況,目前我們使用的身份證由18位構成,包括數字和字母X。那麼,在input輸入框中就需要限制用戶輸入的數據類型。
<el-input
v-model="addStudentList.identitytionId"
// 使用正則表達式,只能輸入阿拉伯數字0-9,和字母X(大寫)
onkeyup="this.value=this.value.replace(/[^\X0-9]/g, '')">
</el-input>
2、其次,查看Element ui 組件庫官網可知,我們可以自定義表單的校驗規則。官網中給出的實例爲:
export default {
data() {
var checkAge = (rule, value, callback) => {
if (!value) {
return callback(new Error('年齡不能爲空'));
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('請輸入數字值'));
} else {
if (value < 18) {
callback(new Error('必須年滿18歲'));
} else {
callback();
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('請輸入密碼'));
} else {
if (this.ruleForm.checkPass !== '') {
this.$refs.ruleForm.validateField('checkPass');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('請再次輸入密碼'));
} else if (value !== this.ruleForm.pass) {
callback(new Error('兩次輸入密碼不一致!'));
} else {
callback();
}
};
return {
ruleForm: {
pass: '',
checkPass: '',
age: ''
},
rules: {
pass: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
],
age: [
{ validator: checkAge, trigger: 'blur' }
]
}
};
},
3、根據官網中的使用方式,在自己的項目中實現爲:
HTML部分:
<el-form :model="addStudentList" :rules="rules" ref="addStudentRef">
<el-form-item label="身份證號:" prop="identitytionId" :label-width="formLabelWidth">
<el-input
v-model="addStudentList.identitytionId"
onkeyup="this.value=this.value.replace(/[^\X0-9]/g, '')">
</el-input>
</el-form-item>
</el-form>
JS部分:
export default {
data() {
var checkIdentitytionId = (rule, value, callback) => {
if (!value) {
return callback(new Error("身份證號不能爲空"));
}
if (!/(^\d{15}$)|(^\d{17}(\d|X|x)$)/.test(value)) {
callback(new Error("你輸入的身份證長度或格式錯誤"));
}
//身份證城市
var aCity = {
11: "北京",
12: "天津",
13: "河北",
14: "山西",
15: "內蒙古",
21: "遼寧",
22: "吉林",
23: "黑龍江",
31: "上海",
32: "江蘇",
33: "浙江",
34: "安徽",
35: "福建",
36: "江西",
37: "山東",
41: "河南",
42: "湖北",
43: "湖南",
44: "廣東",
45: "廣西",
46: "海南",
50: "重慶",
51: "四川",
52: "貴州",
53: "雲南",
54: "西藏",
61: "陝西",
62: "甘肅",
63: "青海",
64: "寧夏",
65: "新疆",
71: "臺灣",
81: "香港",
82: "澳門",
91: "國外"
};
if (!aCity[parseInt(value.substr(0, 2))]) {
callback(new Error("你的身份證地區非法"));
}
// 出生日期驗證
var sBirthday = (
value.substr(6, 4) +
"-" +
Number(value.substr(10, 2)) +
"-" +
Number(value.substr(12, 2))
).replace(/-/g, "/"),
d = new Date(sBirthday);
if (
sBirthday !=
d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate()
) {
callback(new Error("身份證上的出生日期非法"));
}
// 身份證號碼校驗
var sum = 0,
weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2],
codes = "10X98765432";
for (var i = 0; i < value.length - 1; i++) {
sum += value[i] * weights[i];
}
var last = codes[sum % 11]; //計算出來的最後一位身份證號碼
if (value[value.length - 1] != last) {
callback(new Error("你輸入的身份證號非法"));
}
callback();
};
return {
//校驗規則
rules: {
identitytionId: [
{ validator: checkIdentitytionId , trigger: "blur" }
]
}
};
上面的實現方式就是參考官網中的實例進行的。
當這樣寫代碼實現了需求時,那麼問題又來了。按照項目組開發要求,每一vue組件中代碼行數控制在100行左右,光實現身份校驗這一需求就差不多佔用了五分之四,還要有其他的業務需求,顯然把上面這一大段代碼放在這個vue組件中是不太合理的。最好是把它封裝起來,然後直接調用。
4、優化:
既然上面這一校驗規則是在JS部分實現的,那我是不是可以把它單獨寫在js文件中,然後在這個vue組件中引入寫好校驗規則的js文件呢。按照這個思路的實現方式如下:
A、新建校驗規則的js文件:
/*
* @Description:身份證校驗規則.
* @Version: 1.0
* @Author: Nydia
* @Date: 2020-06-28 19:02:19
* @LastEditors: Nydia
* @LastEditTime: 2020-06-29 08:36:09
*/
//在js文件中寫一個身份校驗的方法,在需要身份校驗的vue組件中導入這個js文件,調用暴露出去的校驗方法。傳入的參數爲用戶輸入的身份證號
//校驗身份證號
export function isIdentityId(identityId) {
var patrn = /(^\d{15}$)|(^\d{17}(\d|X|x)$)/;//長度或格式校驗
//地區校驗
var aCity = {
11: "北京",
12: "天津",
13: "河北",
14: "山西",
15: "內蒙古",
21: "遼寧",
22: "吉林",
23: "黑龍江",
31: "上海",
32: "江蘇",
33: "浙江",
34: "安徽",
35: "福建",
36: "江西",
37: "山東",
41: "河南",
42: "湖北",
43: "湖南",
44: "廣東",
45: "廣西",
46: "海南",
50: "重慶",
51: "四川",
52: "貴州",
53: "雲南",
54: "西藏",
61: "陝西",
62: "甘肅",
63: "青海",
64: "寧夏",
65: "新疆",
71: "臺灣",
81: "香港",
82: "澳門",
91: "國外"
};
// 出生日期驗證
var sBirthday = (
identityId.substr(6, 4) +
"-" +
Number(identityId.substr(10, 2)) +
"-" +
Number(identityId.substr(12, 2))
).replace(/-/g, "/"),
d = new Date(sBirthday)
// 身份證號碼校驗 最後4位 包括最後一位的數字/字母X
var sum = 0,
weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2],
codes = "10X98765432";
for (var i = 0; i < identityId.length - 1; i++) {
sum += identityId[i] * weights[i];
}
var last = codes[sum % 11]; //計算出來的最後一位身份證號碼
var errorMsg = '';
if (identityId === '') {
errorMsg = "身份證號不能爲空"
} else if (!patrn.exec(identityId)) {
errorMsg = "你輸入的身份證長度或格式錯誤"
} else if (!aCity[parseInt(identityId.substr(0, 2))]) {
errorMsg = "你的身份證地區非法"
} else if (sBirthday != d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate()) { errorMsg = "身份證上的出生日期非法" } else if (identityId[identityId.length - 1] != last) {
errorMsg = "你輸入的身份證號非法"
}
return errorMsg;
}
B、在需要身份校驗的vue組件中導入js文件:
//項目目錄結構如上圖
import { isIdentityId } from "../people-manage/validate";
C、在該vue組件中的JS部分data屬性中調用js文件中的方法,傳入參數value(input輸入框value值),定義變量接收校驗結果。
data() {
var checkIdentitytionId = (rule, value, callback) => {
var errorMsg = isIdentityId(value);
if (errorMsg != "") {
callback(new Error(errorMsg));
}
};
D、rules中的校驗規則調用方式同上:
//校驗規則
rules: {
identitytionId: [
// { required: true, message: "請輸入身份證號!", trigger: "blur" },
{ validator: checkIdentitytionId , trigger: "blur" }
]
}
將校驗規則封裝後,再調用方法進行校驗,data屬性中的校驗規則回調函數中的代碼由80多行縮減到了3行。優化過後的代碼,要比最初實現方式簡潔了許多。
實現效果【動圖】: