看不惯各种信息收集表,我手写了一个身份证号输入组件

shigen坚持更新文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。 个人IP:shigen

背景

shigen最近的需要填写各种报名表的场景有点多,很多场景都要输入身份证号。对于这些信息,我特别的敏感,所以,我想着能糊弄过去就糊弄过去。之前也确实有乱填,只要凑够了18位,或者我随意改动身份证上的某一位数字就行了。但是,直到我遇到了一种表单:我改一个数字,它发现了,不让我提交!我气急败坏,我要研究一下这玩意怎么实现的。总不至于调用了某云的身份证地址库吧。

于是一个早晨,我就开始坐在了电脑前,研究起这个了。

申明:测试ID来自于互联网,关键信息我也会进行打码,并无实际的数据价值。

研究

身份证号18位,毋庸置疑。够了18位这是基础,完了就是它的生成规则。我特意的查阅了资料:中华人民共和国居民身份证。

反正就是一套规则约束,最后一位校验码通过运算出来的。

原理懂了,那就要开始写代码验证了。为此,我在互联网上找到了一个身份证号,用于实际的测试验证:

代码设计

身份证号的输入,我选用设计一个通用的组件来完成,实现它的灵活性。

level 0ne

第一层次的,我们不引入任何的算法,只对身份证号的规则进行一次校验,这也是很多网站存在的问题。

分装组件
xml 复制代码
 <template>
   <el-form-item :label="label" :prop="prop" :rules="rules">
     <el-input v-model="idNumber" @input="checkIdNumber" :placeholder="placeholder" clearable />
   </el-form-item>
 </template>
 ​
 <script>
 export default {
   props: {
     label: String,
     prop: String,
     // 父组件的表单实例
     parentFormRef: Object,
     placeholder: {
       type: String,
       default: ''
     },
     value: {
       type: String,
       default: ''
     }
   },
   data() {
     return {
       idNumber: this.value,
       rules: [
         {
           validator: this.validateIdNumber,
           trigger: 'blur'
         }
       ]
     };
   },
   watch: {
     value(newValue) {
       this.idNumber = newValue;
     }
   },
   methods: {
     validateIdNumber(rule, value, callback) {
       if (!value) {
         callback(new Error('请输入身份证号码'));
       } else if (!this.check(value)) {
         callback(new Error('请输入有效的身份证号码'));
       } else {
         callback();
       }
     },
     checkIdNumber() {
       this.$nextTick(() => {
         // 确保在下一次 DOM 更新周期后再访问父组件传递的表单实例
         if (this.parentFormRef) {
           this.parentFormRef.validateField('idNumber');
         }
       });
       // 将输入的值通过 input 事件传递给父组件
       this.$emit('input', this.idNumber);
     },
     check(value) {
       const pattern = /^[1-9]\d{5}(18|19|20)?\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}([0-9]|X|x)$/;
       return pattern.test(value);
     },
   }
 };
 </script>

看起来内容小多,关键的逻辑还是对于身份证号的验证,这里选用的是正则表达式。别的就是一些自定义传值的约束和定义。

设计的时候,踩了很多的坑,具体的注意点写在了注释里。

页面使用

在页面中,我们需要这样使用:

xml 复制代码
 <template>
   <div>
     <el-form :model="info" ref="myForm">
       <id-number-input v-model="info.idNumber" :parentFormRef="myForm" label="身份证号码" prop="idNumber"
         placeholder="请输入身份证号码" />
     </el-form>
     <p>idNumber: {{ info.idNumber }}</p>
     <el-button type="primary" @click="submitForm">提交</el-button>
   </div>
 </template>
 ​
 <script>
 import IdNumberInput from '@/components/IdNumberInput.vue';
 ​
 export default {
   components: {
     IdNumberInput
   },
   data() {
     return {
       info: {
         idNumber: '',
       },
       myForm: null,
 ​
     };
   },
   methods: {
     submitForm() {
       this.$refs.myForm.validate((valid) => {
         if (valid) {
           // 表单验证通过,执行提交逻辑
           this.$message.success('表单验证通过,执行提交逻辑');
         } else {
           // 表单验证不通过
           this.$message.error('表单验证不通过');
         }
       });
     },
   }
 };
 </script>

如此,简单的第一步完成,看看效果:

修改出生年月日或者后四位数字的任何一位,照样可以现实验证通过。

level Two

在上一步的基础上,引入了新的校验生成规则;参考了文章身份证号规则校验最全总结。

ini 复制代码
 check2(value) {
   let idcode = value;
 ​
   if (!this.check(idcode)) return false;
 ​
   // 加权因子
   const weightFactor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
   // 校验码
   const checkCode = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
 ​
   const code = String(idcode);
   const last = idcode[17]// 最后一位
 ​
   const seventeen = code.substring(0, 17);
 ​
   // ISO 7064:1983.MOD 11-2 判断最后一位校验码是否正确
   const arr = seventeen.split('');
   const len = arr.length;
   let num = 0;
   for (let i = 0; i < len; i++) {
     num = num + arr[i] * weightFactor[i];
   }
 ​
   // 获取余数
   const resisue = num % 11;
   const lastNo = checkCode[resisue];
   return last === lastNo;
 },

这种方式就是引入了生成规则的校验,这次,随意修改不行了。

以上就是整个探秘+揭秘的整个过程,欢迎评论交流。

与shigen一起,每天不一样!

相关推荐
掘金酱16 分钟前
[稀土掘金 × 火山引擎] AI用量周榜冲刺赛|获奖名单公示
前端·人工智能·后端
泡泡oO35 分钟前
“如果你还在用Superpowers,那我不要和你说话”
前端·后端·全栈
维克兜率天39 分钟前
趋势过滤:避免被“假突破“反复打脸
前端
8年区块链老兵1 小时前
一篇文章教会你:用区块高度读懂比特币链上的每一笔交易
前端
xixichensh1 小时前
前端转做AI程序员第一步——开发一个AI流式对话Demo
前端
小羊没烦恼!2 小时前
系统内部模块(子系统)之间的耦合以及模块(子系统)划分
java·开发语言·前端·数据库·算法·c#
Leslie1652 小时前
聚合不只是 GROUP BY:HashAggregate 与 SortAggregate 的内存账本
前端
ITOM运维行者2 小时前
PHP性能监控怎么做?从响应时间到慢函数的6个关键指标
前端·javascript·后端
成旭先生2 小时前
AI 文本审核 API:一段中文文本判风险等级、命中标签与处置建议
java·前端·人工智能·api接口·内容风控·文本审核·ugc审核
liangshanbo12152 小时前
前端面试题:AI 对话中超长消息导致内存溢出,怎么解决?
java·开发语言·前端