面题系列:表单验证

195 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

我们在开发中对于表单的提交里面的参数验证是家常便饭了,很多ui框架对这个问题也进行了封装,你可以尝试手写出来吗?要求在表单中校验出name,age为必填项,age必须填写数字,tel与email需要符合手机和邮箱格式。

<form id="form">
    <div><label>name:</label><input name="name" /></div>
    <div><label>age:</label><input name="age" /></div>
    <div><label>tel:</label><input name="tel" /></div>
    <div><label>email:</label><input name="email" /></div>
    <button id="btn" type="submit">submit</button>
</form>
<script type="module" src="./app.js"></script>

微信截图_20220321152048.png

考察点

  1. 如何阻止form表单的提交
  2. 是否能手写一些简单的正则表达式
  3. 是否有程序设计的思维,如何避免重复判断

解题思路

  1. e.preventdefault()方法可以阻止元素发生默认的行为,自然可以阻止表单提交。

    document.getElementById("form").addEventListener("submit", e => {
        e.preventDefault()
    })
    
  2. 正则表达式,属于基本功,但能写一些简单的验证基本已经满足团队开发需要了。

    let rules = {
        name: [{
            required: true,
            msg: "名字不得为空"
        }],
        age: [
            {
                required: true,
                msg: "年纪不得为空"
            },
            {
                reg: /(^[1-9]\d*$)/,
                msg: "请输入正确的年纪"
            }
        ],
        tel: [
            {
                reg: /^1\d{10}$/,
                msg: "请输入正确的电话号码"
            }
        ],
        email: [
            {
                reg: /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/,
                msg: "请输入正确的邮箱地址"
            }
        ]
    }
    
  3. 对于考察是否有程序设计思维,如何避免重复判断,所以你肯定不能直接去那正则去反复用if-else去判断提示,而是用更优雅的设计模式来完成。当然实现的方法非常多,可以是传统策略模式,也可以做对象配置判断,用是for...in 与 hasOwnProperty做过滤判断来完成。这里就用后者来实现,而且前者在很多程序设计书中都有案例,这里就不做赘述了。

    function checkFormRules(rules, form) {
        for (const key in rules) {
            if (rules.hasOwnProperty(key) && form.hasOwnProperty(key)) {
                let item = rules[key],
                    value = form[key];
                for (let i = 0, len = item.length; i < len; i++) {
                    const { reg, msg, required } = item[i];
                    if (required && !value) return msg
                    if (reg && (!reg.test(value))) return msg;
                }
            }
        }
    }
    

    这里我们过滤出来要校验的字段,然后一一的进行判断,虽然扩展性不如传统策略模式也没有他优雅,但也可以用最快速度满足题目要求,核心代码极少,面试手写耗时短,如何完善的话,无限使用策略模式完成,增强其扩展性。

    实现

    刚才在分析的时候已经写好了大半,现在只需要使用他就可以完成了题目了。

    ; (function () {
        let form = document.getElementById("form")
        form.addEventListener("submit", e => {
            e.preventDefault()
            let values = { name: "", age: "", tel: "", email: "" }
            for (const key in values) {
                if (values.hasOwnProperty(key)) {
                    values[key] = form[key].value
                }
            }
            let msg = checkFormRules(rules, values)
            if (msg) {
                return alert(msg)
            }
            alert("提交成功")
        })
    })();
    

微信截图_20220321155657.png