阅读 264

Vue 实现用户注册,前端正则校验以及密码强度实时显示

前言

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战。恰逢掘金八月更文挑战,今天向大家分享一些使用 Vue 实现用户注册,同时校验数据格式并实时显示密码强度,希望这个小 demo 能够给初学 Vue 的小伙伴一点小启发,帮助大家更好地去理解和学习。加油,共勉!

页面样式展示

image.png

需求分析

除了默认的性别为男以外,其他字段都是必填项,否则点击注册按钮时不予提交,与此同时提醒用户填写,并将鼠标聚焦到对应未填写的输入框上,填写格式错误时亦是如此。

例如:

image.png

年龄通过监听输入的出生年月,等到输入完立即自动计算得出,此字段不需要用户填写,可设置为 disabled

效果:

1629728795045.gif

当用户按下按键输入密码的同时就开始实时监听判断,密码长度必须大于等于 6 位且不超过 16 位,满足条件就能看到密码强度显示效果,否则将无效。

示例:

gif.gif

代码实现

HTML 结构 + 简单的内联 CSS 样式

<div id="register">
    <table>
        <tr>
            <th>用户名:</th>
            <td><input type="text" id="username" placeholder="请输入用户名" autocomplete="off" v-model="user.username"/></td>
        </tr>
        <tr>
            <th>姓名:</th>
            <td><input type="text" id="name" placeholder="请输入姓名" autocomplete="off" v-model="user.name"/></td>
        </tr>
        <tr>
            <th>性别:</th>
            <td>
                <label>
                    <input type="radio" name="sex" value="1" checked v-model="user.gender"/>
                    &nbsp;男
                </label>
                <label>
                    <input type="radio" name="sex" value="0" v-model="user.gender"/>
                    &nbsp;女
                </label>
            </td>
        </tr>
        <tr>
            <th>出生年月:</th>
            <td>
                <label>
                    <input type="date" id="birthday" placeholder="请选择出生年月" v-model="user.birthday"/>
                </label>
            </td>
        </tr>
        <tr>
            <th>年龄:</th>
            <td>
                <input type="number" id="age" disabled v-model="user.age"/>
            </td>
        </tr>
        <tr>
            <th>手机号码:</th>
            <td>
                <input type="tel" id="mobile" placeholder="请输入电话号码" autocomplete="off" v-model="user.mobile"/>
            </td>
        </tr>
        <tr>
            <th>密码:</th>
            <td><input type="password" id="password" placeholder="请输入密码" autocomplete="off" v-model="user.password" v-on:keyup="strengthShow"/></td>
        </tr>
        <tr>
            <th style="width: max-content;"></th>
            <td>
                <span id="weak">弱</span>
                <span id="medium">中</span>
                <span id="strong">强</span>
            </td>
        </tr>
        <tr>
            <th style="width: max-content;"></th>
            <td><span style="color: red; font-size: smaller;">{{msg}}</span></td>
        </tr>
        <tr>
            <th style="width: max-content;"></th>
            <td>
                <button @click="checkForm">注册</button>
                <button onclick="history.back()" style="display: inline-block;margin-left: 70px">返回</button>
            </td>
        </tr>
    </table>
</div>
复制代码

这里不做过多的解释,代码并不复杂,主要是密码强度显示条样式:

#weak,
#medium,
#strong {
    display: inline-block;
    height: 15px;
    width: 48px;
    border-top: 4px solid gainsboro;
    margin-left: 3px;
    font-size: 12px;
    text-align: center;
}
复制代码

Vue 部分

var vm = new Vue({
    el: '#register',
    data: {
        user: {
            username: null,
            name: null,
            gender: 1,
            birthday: null,
            age: 0,
            mobile: null,
            password: null
        },
        msg: null
    },
    methods: {
        checkForm: function () {
            const emptyKey = isEmptyInput();
            switch (emptyKey) {
                case 'username':
                    msgForUser('用户名不能为空!', emptyKey);
                    break;
                case 'name':
                    msgForUser('姓名不能为空!', emptyKey);
                    break;
                case 'birthday':
                    msgForUser('出生年月不能为空!', emptyKey);
                    break;
                case 'mobile':
                    msgForUser('手机号码不能为空!', emptyKey);
                    break;
                case 'password':
                    msgForUser('密码不能为空!', emptyKey);
                    break;
                default:
                    // 非空验证判断完毕,对电话号码的格式的正则验证
                    if(!(/^1([345789])\d{9}$/.test(this.user.mobile))) {
                        this.msg = '手机号码格式有误!';
                    }else if(this.user.password.length < 6 || this.user.password.length > 16) {
                        this.msg = '密码长度必须在6-16位之间!'
                    }else { // 都验证完了之后,将注册信息请求到后端,注册一个新用户
                        const user = this.user;
                        $.ajax({
                            type: 'POST',
                            url: './registerUser',
                            data: user,
                            success: function (data) {
                                handleRegister(data);
                            },
                            error: function (error) {
                                alert(error);
                            }
                        });
                    }
            }
        },
        strengthShow: function () { // 密码强度实时显示
            // 弱密码:全是数字或全是字母,6-16个字符
            const weakReg = /^[0-9]{6,16}$|^[a-zA-Z]{6,16}$/;
            // 中密码:数字和26个英文字母,6-16个字符
            const mediumReg = /^[A-Za-z0-9]{6,16}$/;
            // 强密码:由数字、26个英文字母或者下划线组成的字符串,6-16个字符
            const strongReg = /^\w{6,16}$/;
            var password = this.user.password;
            if(null !== password) {
                if(password.length >= 6 && password.length <= 16) {
                    if(password.match(weakReg)) {
                        $('#weak').css('borderTopColor', 'yellow');
                    }else if(password.match(mediumReg)) {
                        $('#weak').css('borderTopColor', 'yellow');
                        $('#medium').css('borderTopColor', 'blue');
                    }else if(password.match(strongReg)) {
                        $('#weak').css('borderTopColor', 'yellow');
                        $('#medium').css('borderTopColor', 'blue');
                        $('#strong').css('borderTopColor', 'green');
                    }
                }else {
                    $('#weak').css('borderTopColor', 'gainsboro');
                    $('#medium').css('borderTopColor', 'gainsboro');
                    $('#strong').css('borderTopColor', 'gainsboro');
                }
            }
        }
    },
    watch: {
        // 监视对象中属性值变化
        user: {
            handler: function () {
                var birthday = this.user.birthday;
                if(birthday !== null) {
                    var gap = getGrowAge(birthday);
                    // 截取岁之前的数字,作为计算的年龄
                    var index = gap.indexOf('岁');
                    this.user.age = parseInt(gap.substring(0,index));
                }
                this.msg = null;
            },
            deep: true
        }
    }
});
复制代码

Vue 代码中定义了一个用户对象以及给用户的提醒信息,定义了两个方法,其中一个方法用于表单验证,并通过 @click="checkForm" 也就是 v-on:click="checkForm" 简写,注册按钮绑定了一个点击事件,点击按钮后从上往下一一进行验证。

上述代码中包含了三个封装后的函数,通过对注册用户对象的循环,判断属性值是否为 null 或者为 空格字符串,出现任意一种情况,就结束循环返回属性名,并通过 msgForUser() 函数将提醒信息反馈给用户,并通过属性名找到 input 表单实现聚焦,等待用户再次输入。第三个函数,显示注册成功与否的消息,并实现页面等待跳转。

三个函数具体实现如下:

// 进行表单判断,验证用户输入
function msgForUser(text, id) {
    vm.msg = text;
    const obj = $(`#${id}`);
    obj.focus();
}

// 判断是否表单是否为空,返回 key
function isEmptyInput() {
    const entries = Object.entries(vm.user);
    var key = null;
    for(const [k, v] of entries) {
        if(v === null || (v.toString()).match(/^[ ]*$/)) {
            key = k;
            break;
        }
    }
    return key;
}

// 将注册成功与否的消息显示,并在 750 毫秒后跳转到菜单首页
function handleRegister(data) {
    alert(data.msg);
    setTimeout(function () {
        // 登录成功后跳转到首页
        window.location.href = '../index.html';
    },750);
}
复制代码

v-model="user.password" v-on:keyup="strengthShow" 密码通过双向绑定,可以通过添加键盘按下事件动态地监听密码状态,并实时显示密码强度。

那如何根据输入的出生日期动态计算年龄呢?

顺手写一个工具函数,将当前时间转换为秒减去生日转换后的秒数,再用得到的差转化为相差的年数、月数、小时数甚至分秒数。注意闰年的情况,获取不同年份下不同月份的天数。

// 获取出生年龄,周岁、月、天、时、分、秒
function getGrowAge(birthday){
    var now = new Date();
    var year = now.getFullYear();
    var month = now.getMonth() + 1;
    var day = now.getDate();
    var hour = now.getHours();
    var minute = now.getMinutes();
    var second = now.getSeconds();

    var myDate = new Date(birthday);
    var myYear = myDate.getFullYear();
    var myMonth = myDate.getMonth() + 1;
    var myDay = myDate.getDate();
    var myHour = myDate.getHours();
    var myMinute = myDate.getMinutes();
    var mySecond = myDate.getSeconds();

    var gapSecond = second - mySecond;
    if(gapSecond < 0){
        minute -= 1;
        gapSecond = 60 - mySecond + second;
    }
    //gapSecond = gapSecond<10? ("0"+gapSecond): gapSecond;
    var gapMinute = minute - myMinute;
    if(gapMinute < 0){
        hour -= 1;
        gapMinute = 60 - myMinute + minute;
    }
    //gapMinute = gapMinute<10? ("0"+gapMinute): gapMinute;
    var gapHour = hour - myHour;
    if(gapHour < 0){
        day -= 1;
        gapHour = 24 - myHour + hour;
    }
    //gapHour = gapHour<10? ("0"+gapHour): gapHour;
    var gapDay = day - myDay;
    if(gapDay < 0){
        month -= 1;
        gapDay = getDaysOfMonth(birthday) - myDay + day;
    }
    //gapDay = gapDay<10? ("0"+gapDay): gapDay;
    var gapMonth = month - myMonth;
    if(gapMonth < 0){
        year -= 1;
        gapMonth = 12 - myMonth + month;

    }
    //gapMonth = gapMonth<10? ("0"+gapMonth): gapMonth;
    var gapYear = year - myYear;
    if(gapYear < 0){
        gapYear = 0;
    }

    var dateStr = (gapYear>0?gapYear:'0') + '岁' +
        (gapMonth>0?gapMonth:'0') + '月' +
        (gapDay>0?gapDay:'0') + '天' +
        (gapHour>0?gapHour:'0') + '时' +
        (gapMinute>0?gapMinute:'0') + '分' +
        (gapSecond>0?gapSecond:'0') + '秒';
    return dateStr;
}

// 获取当月的天数
function getDaysOfMonth(dateStr){
    var date = new Date(dateStr);
    var year = date.getFullYear();
    var mouth = date.getMonth() + 1;
    var day = 0;

    if(mouth == 2)  {
        day= isLeapYear(year) ? 29 : 28;
    } else if(mouth == 1 || mouth == 3 || mouth == 5 ||
        mouth == 7 || mouth == 8 || mouth == 10 || mouth == 12) {
        day= 31;
    } else {
        day= 30;
    }
    return day;
}

// 判断是否为闰年
function isLeapYear(year){
    return (year%4==0 && year%100!=0)||(year%400==0);
}
复制代码

将写好的函数放到一个 js 文件中,在该页面中引入即可,并配合 Vue 的数据绑定,轻松实现理想中的效果,是不是很简单呢?!

结尾

撰文不易,欢迎大家点赞、评论,你的关注、点赞是我坚持的不懈动力,感谢大家能够看到这里!Peace & Love。

文章分类
前端
文章标签