4-8-编程练习,blur事件如何简化优化呢?
我的程序中,绑定blur事件有很多代码是重复的,其差异只是inputObject对象的属性值不同。请老师帮忙看看,如何简化达到良好的可读性和可维护性。代码略多,请老师耐心慢慢看。
我的程序目录如下:
index.html文件如下:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>4-8-编程练习</title> <meta charset="UTF-8"> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <link type="text/css" rel="stylesheet" href="index.css"> </head> <body> <!-- 标题 --> <h1 class="heading">用户注册</h1> <!-- 注册表单 --> <form class="register" method="post"> <!-- 第1项:用户名 --> <p class="register__p"> <label class="register__p__item">用户名:</label> <input type="text" class="register__p__input" placeholder="6-20位的英文字母、数字、下划线,字母开头"> <label class="register__p__tip"></label> </p> <!-- 第2项:登陆密码 --> <p class="register__p"> <label class="register__p__item">登陆密码:</label> <input type="password" class="register__p__input" placeholder="6-18位的英文字母、数字、特殊符号,不能有空格"> <label class="register__p__tip"></label> </p> <!-- 第3项:确认密码 --> <p class="register__p"> <label class="register__p__item">确认密码:</label> <input type="password" class="register__p__input" placeholder="请再次输入密码"> <label class="register__p__tip"></label> </p> <!-- 第4项:姓名 --> <p class="register__p"> <label class="register__p__item">姓名:</label> <input type="text" class="register__p__input" placeholder="2-4个汉字"> <label class="register__p__tip"></label> </p> <!-- 第5项:性别 --> <p class="register__p"> <label class="register__p__item">性别:</label> <select class="register__p__gender"> <option value="M">男</option> <option value="F">女</option> </select> </p> <!-- 第6项:身份证号码 --> <p class="register__p"> <label class="register__p__item">身份证号码:</label> <input type="text" class="register__p__input" placeholder="15或18位数字(若最后一位是X则原样输入)"> <label class="register__p__tip"></label> </p> <!-- 第7项:手机号码 --> <p class="register__p"> <label class="register__p__item">手机号码:</label> <input type="text" class="register__p__input" placeholder="中国大陆的11位手机号码"> <label class="register__p__tip"></label> </p> <!-- 第8项:电子邮箱 --> <p class="register__p"> <label class="register__p__item">电子邮箱:</label> <input type="text" class="register__p__input" placeholder="请输入电子邮箱"> <label class="register__p__tip"></label> </p> <!-- 提交按钮 --> <p class="register__p-submit"> <input type="button" value="提交" class="register__p-submit__submit"> </p> </form> <script type="text/javascript" src="index.js"></script> </body> </html>
index.css文件如下:
body, h1, p, label, form, input { margin: 0; padding: 0; } body { font-size: 16px; font-family: "Microsoft YaHei", "微软雅黑"; background-color: #EEE; } /*标题*/ .heading { width: 100%; height: 50px; line-height: 50px; font-size: 25px; text-indent: 10%; letter-spacing: .8em; color: #FFF; background-color: #3090D0; } /*注册表单*/ .register { margin: 40px auto; width: 1000px; } /*注册表单里的<p>标签*/ .register__p { margin: 5px auto; width: 1000px; height: 40px; line-height: 40px; } /*input输入框前面的文字*/ .register__p__item { display: inline-block; width: 120px; height: 40px; line-height: 40px; text-align: right; color: #233; } /*input输入框*/ .register__p__input { width: 420px; height: 22px; line-height: 22px; font-size: 18px; } /*下拉列表:性别选择*/ .register__p__gender { width: 200px; height: 24px; } /*input输入框后面的提示文字*/ .register__p__tip { margin-left: 2px; display: inline-block; height: 22px; line-height: 22px; } /*输入正确时提示文字的颜色*/ .register__p__tip-valid { color: #080; } /*输入错误时提示文字的颜色*/ .register__p__tip-invalid { color: #F00; } /*提交段落*/ .register__p-submit { margin: 50px auto 5px; width: 1000px; height: 40px; text-indent: 300px; } /*提交按钮*/ .register__p-submit__submit { border: 1px solid #666; border-radius: 5px; width: 100px; height: 40px; line-height: 40px; font-size: 20px; color: #FFF; background-color: #26B; transition: all .3s; } /*提交按钮hover效果*/ .register__p-submit__submit:hover { color: #F00; background-color: #CCF; cursor: pointer; }
index.js文件如下:
// 获取注册表单元素 let registerForm = document.querySelector(".register"); // 获取输入框input元素 let registerInputs = registerForm.getElementsByClassName("register__p__input"); // 获取显示提示文字的label元素 let registerLabels = registerForm.getElementsByClassName("register__p__tip"); // 输入框input元素组成一个对象(7个属性,每个属性都是DOM元素) let inputObject = { // 用户名input元素 "username": registerInputs[0], // 登录密码input元素 "password": registerInputs[1], // 确认密码input元素 "confirmPassword": registerInputs[2], // 姓名input元素 "trueName": registerInputs[3], // 身份证号码input元素 "idNumber": registerInputs[4], // 手机号码input元素 "phoneNumber": registerInputs[5], // 电子邮箱input元素 "email": registerInputs[6], }; // 显示提示文字的label元素组成一个对象(7个属性,每个属性都是DOM元素) let labelObject = { // 用户名input元素 "username": registerLabels[0], // 登录密码input元素 "password": registerLabels[1], // 确认密码input元素 "confirmPassword": registerLabels[2], // 姓名input元素 "trueName": registerLabels[3], // 身份证号码input元素 "idNumber": registerLabels[4], // 手机号码input元素 "phoneNumber": registerLabels[5], // 电子邮箱input元素 "email": registerLabels[6], }; // 正则表达式,组成一个对象(6个属性) const regExpObject = { // 用户名:6-20位的英文字母、数字、下划线,字母开头 "username": /^[a-zA-Z]\w{5,19}$/, // 密码:6-18位的英文字母、数字、特殊符号,不能有空格 // 即除了空白字符和换行符以外的其它任意字符 "password": /^[^\s\n]{6,18}$/, // 姓名:2-4个汉字 "trueName": /^[\u4E00-\u9FEF]{2,4}$/, // 身份证号码:15或18位数字(若最后一位是X则原样输入) "idNumber": /^(\d{15}|\d{17}(\d|X))$/i, // 移动有17个号段: // 134、135、136、137、138、139、147、150、151、152、157、158、159、182、183、187、188 // 联通有7个号段: // 130、131、132、155、156、185、186 // 电信有4个号段: // 133、153、180、189 // 综上,手机号码前3位只有这4种情况: // 【1】130~139,即13\d // 【2】147 // 【3】150~153,155~159,即15[0-35-9] // 【4】180、182、183、185~189,即18[025-9] "phoneNumber": /^(13\d|147|15[0-35-9]|18[0235-9])\d{8}$/, // 邮箱格式,如:123456@qq.com、lulu_1994@sina.com、imooc_programmer@foxmail.com.cn // 可见字符串中一定含有字符"@",在此作出如下规定: // 字符"@"前面的字符(登录名):只允许是英文字母、数字、下划线 // 字符"@"后面的字符(主机名、域名):除了结尾单词后面没有点号,其余单词后面都有点号 "email": /^\w+@([a-zA-Z]+\.)*[a-zA-Z]+$/, }; // 输入错误时的提示文字(7个属性) const tipObject = { // 用户名错误时 "username": "6-20位的英文字母、数字、下划线,字母开头", // 登录密码错误时 "password": "6-18位的英文字母、数字、特殊符号,不能有空格", // 确认密码错误时 "confirmPassword": "两次输入的密码不一致", // 姓名错误时 "trueName": "真实姓名要求是2-4个汉字", // 身份证号码错误时 "idNumber": "15或18位数字(若最后一位是X则原样输入)", // 手机号码错误时 "phoneNumber": "请输入真实的11位手机号码", // 电子邮箱错误时 "email": "电子邮箱格式不正确", }; // 根据手机号码的前3位,判断运营商,参数是11位手机号码 let getProvider = function(phoneNumber) { // 含有3个对象的数组 let providerArray = [ // 移动有17个号段: // 134、135、136、137、138、139、147、150、151、152、157、158、159、182、183、187、188 { regExp: /^(13[4-9]|147|15[012789]|18[2378])/, providerName: "中国移动", }, // 联通有7个号段: // 130、131、132、155、156、185、186 { regExp: /^(13[012]|15[56]|18[56])/, providerName: "中国联通", }, // 电信有4个号段: // 133、153、180、189 { regExp: /^(133|153|18[09])/, providerName: "中国电信", }, ]; // 若不是三大运营商,则归为未知运营商 for (let i in providerArray) { if (providerArray[i].regExp.test(phoneNumber)) { return providerArray[i].providerName; } } return "未知运营商"; }; // 各个input表单是否验证通过(7个属性) let isPassed = { // 用户名是否验证通过 "username": false, // 登录密码是否验证通过 "password": false, // 确认密码是否验证通过 "confirmPassword": false, // 姓名是否验证通过 "trueName": false, // 身份证号码是否验证通过 "idNumber": false, // 手机号码是否验证通过 "phoneNumber": false, // 电子邮箱是否验证通过 "email": false, }; // 用户名input表单的blur事件 inputObject["username"].addEventListener("blur", function() { if (!this.value) { // 若未输入内容,则不显示提示文字 labelObject["username"].innerText = ""; } else { if (regExpObject["username"].test(this.value)) { // 若验证通过,则显示绿色的提示文字 isPassed["username"] = true; labelObject["username"].innerText = "OK"; labelObject["username"].className = "register__p__tip-valid"; } else { // 若验证失败,则显示红色的提示文字 isPassed["username"] = false; labelObject["username"].innerText = tipObject["username"]; labelObject["username"].className = "register__p__tip-invalid"; } } }); // 登陆密码input表单的blur事件 inputObject["password"].addEventListener("blur", function() { if (!this.value) { // 若未输入内容,则不显示提示文字 labelObject["password"].innerText = ""; } else { if (regExpObject["password"].test(this.value)) { // 若验证通过,则显示绿色的提示文字 isPassed["password"] = true; labelObject["password"].innerText = "OK"; labelObject["password"].className = "register__p__tip-valid"; } else { // 若验证失败,则显示红色的提示文字 isPassed["password"] = false; labelObject["password"].innerText = tipObject["password"]; labelObject["password"].className = "register__p__tip-invalid"; } } }); // 确认密码input表单的blur事件 inputObject["confirmPassword"].addEventListener("blur", function() { if (!inputObject["password"].value || !isPassed["password"] || !this.value) { // 若存在以下三种情况之一:登陆密码未输入、登陆密码未通过、确认密码未输入, // 则不显示提示文字 labelObject["confirmPassword"].innerText = ""; } else { if (this.value === inputObject["password"].value) { // 若验证通过,则显示绿色的提示文字 isPassed["confirmPassword"] = true; labelObject["confirmPassword"].innerText = "两次密码一致"; labelObject["confirmPassword"].className = "register__p__tip-valid"; } else { // 若验证失败,则显示红色的提示文字 isPassed["confirmPassword"] = false; labelObject["confirmPassword"].innerText = tipObject["confirmPassword"]; labelObject["confirmPassword"].className = "register__p__tip-invalid"; } } }); // 姓名input表单的blur事件 inputObject["trueName"].addEventListener("blur", function() { if (!this.value) { // 若未输入内容,则不显示提示文字 labelObject["trueName"].innerText = ""; } else { if (regExpObject["trueName"].test(this.value)) { // 若验证通过,则显示绿色的提示文字 isPassed["trueName"] = true; labelObject["trueName"].innerText = "OK"; labelObject["trueName"].className = "register__p__tip-valid"; } else { // 若验证失败,则显示红色的提示文字 isPassed["trueName"] = false; labelObject["trueName"].innerText = tipObject["trueName"]; labelObject["trueName"].className = "register__p__tip-invalid"; } } }); // 身份证号码input表单的blur事件 inputObject["idNumber"].addEventListener("blur", function() { if (!this.value) { // 若未输入内容,则不显示提示文字 labelObject["idNumber"].innerText = ""; } else { if (regExpObject["idNumber"].test(this.value)) { // 若验证通过,则显示绿色的提示文字 isPassed["idNumber"] = true; labelObject["idNumber"].innerText = "OK"; labelObject["idNumber"].className = "register__p__tip-valid"; } else { // 若验证失败,则显示红色的提示文字 isPassed["idNumber"] = false; labelObject["idNumber"].innerText = tipObject["idNumber"]; labelObject["idNumber"].className = "register__p__tip-invalid"; } } }); // 手机号码input表单的blur事件 inputObject["phoneNumber"].addEventListener("blur", function() { if (!this.value) { // 若未输入内容,则不显示提示文字 labelObject["phoneNumber"].innerText = ""; } else { if (regExpObject["phoneNumber"].test(this.value)) { // 若验证通过,则显示绿色的提示文字 isPassed["phoneNumber"] = true; labelObject["phoneNumber"].innerText = getProvider(this.value); labelObject["phoneNumber"].className = "register__p__tip-valid"; } else { // 若验证失败,则显示红色的提示文字 isPassed["phoneNumber"] = false; labelObject["phoneNumber"].innerText = tipObject["phoneNumber"]; labelObject["phoneNumber"].className = "register__p__tip-invalid"; } } }); // 电子邮箱input表单的blur事件 inputObject["email"].addEventListener("blur", function() { if (!this.value) { // 若未输入内容,则不显示提示文字 labelObject["email"].innerText = ""; } else { if (regExpObject["email"].test(this.value)) { // 若验证通过,则显示绿色的提示文字 isPassed["email"] = true; labelObject["email"].innerText = "OK"; labelObject["email"].className = "register__p__tip-valid"; } else { // 若验证失败,则显示红色的提示文字 isPassed["email"] = false; labelObject["email"].innerText = tipObject["email"]; labelObject["email"].className = "register__p__tip-invalid"; } } }); // 获取提交按钮 const submitButton = registerForm.querySelector(".register__p-submit__submit"); // 提交按钮的点击事件 submitButton.addEventListener("click", function() { // 表示能否通过所有验证,从而提交 let canSubmit = true; // 对每一项重新验证 for (let idx in inputObject) { inputObject[idx].blur(); // 验证结果使用逻辑与进行运算 canSubmit = canSubmit && isPassed[idx]; } // 最终判断能否提交 if (canSubmit) { alert("验证通过!"); } else { alert("请把所有项目输入完善!"); } });
22
收起
正在回答
2回答
同学你好,blur事件的优化,老师这里只给同学提供个思路,同学可以尝试着实现一下。将blur事件封装为一个函数,可以传两个参数 ,第一个参数传表单元素,第二个元素传正则验证的表达式,当验证通过时,就让某个表单元素的flag设置为true。
如果我的回答帮助到了你,欢迎采纳,祝学习愉快~
我学习太差被关起来了
2020-01-05 19:25:30
改进后的JS代码,index.js文件如下:
// 获取注册表单元素 let registerForm = document.querySelector(".register"); // 获取输入框input元素 let registerInputs = registerForm.getElementsByClassName("register__p__input"); // 获取显示提示文字的label元素 let registerLabels = registerForm.getElementsByClassName("register__p__tip"); // 输入框input元素组成一个对象(7个属性,每个属性都是DOM元素) let inputObject = { // 用户名input元素 "username": registerInputs[0], // 登录密码input元素 "password": registerInputs[1], // 确认密码input元素 "confirmPassword": registerInputs[2], // 姓名input元素 "trueName": registerInputs[3], // 身份证号码input元素 "idNumber": registerInputs[4], // 手机号码input元素 "phoneNumber": registerInputs[5], // 电子邮箱input元素 "email": registerInputs[6], }; // 显示提示文字的label元素组成一个对象(7个属性,每个属性都是DOM元素) let labelObject = { // 用户名input元素 "username": registerLabels[0], // 登录密码input元素 "password": registerLabels[1], // 确认密码input元素 "confirmPassword": registerLabels[2], // 姓名input元素 "trueName": registerLabels[3], // 身份证号码input元素 "idNumber": registerLabels[4], // 手机号码input元素 "phoneNumber": registerLabels[5], // 电子邮箱input元素 "email": registerLabels[6], }; // 正则表达式,组成一个对象(6个属性) const regExpObject = { // 用户名:6-20位英文字母、数字、下划线,字母开头 "username": /^[a-zA-Z]\w{5,19}$/, // 密码:6-18位英文字母、数字、特殊符号,不能有空格 // 即除了空白字符和换行符以外的其它任意字符 "password": /^[^\s\n]{6,18}$/, // 姓名:2-4个汉字 "trueName": /^[\u4E00-\u9FEF]{2,4}$/, // 身份证号码:15或18位数字(若最后一位是X则原样输入) "idNumber": /^(\d{15}|\d{17}(\d|X))$/i, // 移动有17个号段: // 134、135、136、137、138、139、147、150、151、152、157、158、159、182、183、187、188 // 联通有7个号段: // 130、131、132、155、156、185、186 // 电信有4个号段: // 133、153、180、189 // 综上,手机号码前3位只有这4种情况: // 【1】130~139,即13\d // 【2】147 // 【3】150~153,155~159,即15[0-35-9] // 【4】180、182、183、185~189,即18[0235-9] "phoneNumber": /^(13\d|147|15[0-35-9]|18[0235-9])\d{8}$/, // 电子邮箱格式,如:123456@qq.com、lulu_1994@sina.com、imooc_programmer@foxmail.com.cn // "@"前面的字符(登录名):只允许是英文字母、数字、下划线 // "@"后面的字符(主机名、域名):只允许是英文字母,除了结尾单词后面没有点号,其余单词后面都有点号 "email": /^\w+@([a-zA-Z]+\.)+[a-zA-Z]+$/, }; // 输入错误时的提示文字(7个属性) const tipObject = { // 用户名错误时 "username": "6-20位英文字母、数字、下划线,字母开头", // 登录密码错误时 "password": "6-18位英文字母、数字、特殊符号,不能有空格", // 确认密码错误时 "confirmPassword": "两次输入的密码不一致", // 姓名错误时 "trueName": "真实姓名要求是2-4个汉字", // 身份证号码错误时 "idNumber": "15或18位数字(若最后一位是X则原样输入)", // 手机号码错误时 "phoneNumber": "请输入有效的11位手机号码", // 电子邮箱错误时 "email": "电子邮箱格式不正确", }; // 根据手机号码的前3位,判断运营商,参数是11位手机号码 let getProvider = function(phoneNumber) { // 含有3个对象的数组 let providerArray = [ // 移动有17个号段: // 134、135、136、137、138、139、147、150、151、152、157、158、159、182、183、187、188 { regExp: /^(13[4-9]|147|15[012789]|18[2378])/, providerName: "中国移动", }, // 联通有7个号段: // 130、131、132、155、156、185、186 { regExp: /^(13[012]|15[56]|18[56])/, providerName: "中国联通", }, // 电信有4个号段: // 133、153、180、189 { regExp: /^(133|153|18[09])/, providerName: "中国电信", }, ]; // 若不是三大运营商,则归为未知运营商 for (let i in providerArray) { if (providerArray[i].regExp.test(phoneNumber)) { return providerArray[i].providerName; } } return "未知运营商"; }; // 各个input表单是否验证通过(7个属性) let isPassed = { // 用户名是否验证通过 "username": false, // 登录密码是否验证通过 "password": false, // 确认密码是否验证通过 "confirmPassword": false, // 姓名是否验证通过 "trueName": false, // 身份证号码是否验证通过 "idNumber": false, // 手机号码是否验证通过 "phoneNumber": false, // 电子邮箱是否验证通过 "email": false, }; // 给input元素绑定blur事件 function blurEvent(idx) { inputObject[idx].addEventListener("blur", function() { if (!this.value) { // 若未输入内容,则不显示提示文字 isPassed[idx] = false; labelObject[idx].innerText = ""; } else { if (regExpObject[idx].test(this.value)) { // 若验证通过,则显示绿色的提示文字 isPassed[idx] = true; labelObject[idx].innerText = idx === "phoneNumber" ? getProvider(this.value) : "OK"; labelObject[idx].className = "register__p__tip-valid"; } else { // 若验证失败,则显示红色的提示文字 isPassed[idx] = false; labelObject[idx].innerText = tipObject[idx]; labelObject[idx].className = "register__p__tip-invalid"; } } }); } // 用户名input表单绑定blur事件 blurEvent("username"); // 登陆密码input表单绑定blur事件 blurEvent("password"); // 确认密码input表单绑定blur事件 inputObject["confirmPassword"].addEventListener("blur", function() { if (!inputObject["password"].value || !isPassed["password"] || !this.value) { // 若存在以下三种情况之一:登陆密码未输入、登陆密码未通过、确认密码未输入, // 则不显示提示文字 isPassed["confirmPassword"] = false; labelObject["confirmPassword"].innerText = ""; } else { if (this.value === inputObject["password"].value) { // 若验证通过,则显示绿色的提示文字 isPassed["confirmPassword"] = true; labelObject["confirmPassword"].innerText = "两次密码一致"; labelObject["confirmPassword"].className = "register__p__tip-valid"; } else { // 若验证失败,则显示红色的提示文字 isPassed["confirmPassword"] = false; labelObject["confirmPassword"].innerText = tipObject["confirmPassword"]; labelObject["confirmPassword"].className = "register__p__tip-invalid"; } } }); // 姓名input表单绑定blur事件 blurEvent("trueName"); // 身份证号码input表单绑定blur事件 blurEvent("idNumber"); // 手机号码input表单绑定blur事件 blurEvent("phoneNumber"); // 电子邮箱input表单绑定blur事件 blurEvent("email"); // 获取提交按钮 const submitButton = registerForm.querySelector(".register__p-submit__submit"); // 提交按钮的点击事件 submitButton.addEventListener("click", function() { // 表示能否通过所有验证,从而提交 let canSubmit = true; for (let idx in inputObject) { canSubmit = canSubmit && isPassed[idx]; } // 最终判断能否提交 canSubmit ? alert("验证通过!") : alert("请把所有项目输入完善!"); });
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星