表单验证

表单验证概述

表单验证是确保用户输入数据有效性的重要手段,分为客户端验证和服务器端验证。

东巴文(db-w.cn) 认为:良好的表单验证能提升用户体验,减少服务器压力。

验证类型

客户端验证

客户端验证在浏览器端进行,提供即时反馈:

东巴文验证类型对比

验证类型 执行位置 优点 缺点
HTML5验证 浏览器 简单、快速 功能有限
JavaScript验证 浏览器 灵活、强大 需编写代码
服务器验证 服务器 安全可靠 需要网络请求

验证时机

东巴文验证时机

时机 事件 说明
输入时 input 实时验证
失去焦点 blur 离开字段时
提交前 submit 提交表单时
手动触发 checkValidity() 自定义时机

HTML5验证属性

required属性

指定字段为必填:

<form>
    <input type="text" name="username" required>
    <input type="email" name="email" required>
    <textarea name="message" required></textarea>
    <button type="submit">提交</button>
</form>

东巴文说明

  • 必填字段为空时,表单无法提交
  • 浏览器会显示默认错误提示
  • 可通过CSS的:required伪类设置样式

pattern属性

使用正则表达式验证:

<form>
    <!-- 手机号验证 -->
    <input type="tel" name="phone" 
           pattern="[0-9]{11}" 
           title="请输入11位手机号"
           placeholder="请输入手机号">
    
    <!-- 用户名验证(字母开头,允许字母数字下划线) -->
    <input type="text" name="username" 
           pattern="[a-zA-Z][a-zA-Z0-9_]{5,19}" 
           title="用户名必须以字母开头,6-20个字符"
           placeholder="用户名">
    
    <!-- 邮政编码验证 -->
    <input type="text" name="zipcode" 
           pattern="[0-9]{6}" 
           title="请输入6位邮政编码"
           placeholder="邮政编码">
    
    <!-- 身份证号验证 -->
    <input type="text" name="idcard" 
           pattern="[0-9]{17}[0-9Xx]" 
           title="请输入18位身份证号"
           placeholder="身份证号">
    
    <button type="submit">提交</button>
</form>

东巴文常用正则表达式

验证内容 正则表达式 说明
手机号 [0-9]{11} 11位数字
邮箱 [^@]+@[^@]+\.[^@]+ 简单邮箱格式
用户名 [a-zA-Z][a-zA-Z0-9_]{5,19} 字母开头,6-20字符
密码 .{6,20} 6-20个任意字符
身份证 [0-9]{17}[0-9Xx] 18位身份证号
邮编 [0-9]{6} 6位数字
网址 https?://.+ http或https开头

minmax属性

用于数值和日期范围验证:

<form>
    <!-- 年龄范围 -->
    <input type="number" name="age" min="1" max="120" value="25">
    
    <!-- 日期范围 -->
    <input type="date" name="birthday" min="1900-01-01" max="2024-12-31">
    
    <!-- 分数范围 -->
    <input type="number" name="score" min="0" max="100" step="0.5">
    
    <button type="submit">提交</button>
</form>

minlengthmaxlength属性

限制文本长度:

<form>
    <!-- 用户名长度 -->
    <input type="text" name="username" 
           minlength="6" maxlength="20" 
           placeholder="6-20个字符">
    
    <!-- 密码长度 -->
    <input type="password" name="password" 
           minlength="8" maxlength="32" 
           placeholder="8-32个字符">
    
    <!-- 留言长度 -->
    <textarea name="message" 
              minlength="10" maxlength="500" 
              placeholder="请输入10-500个字符"></textarea>
    
    <button type="submit">提交</button>
</form>

type属性验证

特定类型的输入格式验证:

<form>
    <!-- 邮箱验证 -->
    <input type="email" name="email" placeholder="请输入邮箱">
    
    <!-- 网址验证 -->
    <input type="url" name="website" placeholder="请输入网址">
    
    <!-- 电话验证 -->
    <input type="tel" name="phone" pattern="[0-9]{11}" placeholder="请输入手机号">
    
    <button type="submit">提交</button>
</form>

东巴文type验证说明

类型 验证规则 示例
email 必须包含@符号 test@example.com
url 必须是有效URL https://db-w.cn
tel 无默认验证(需pattern) 13800138000
number 必须是数字 123

约束验证API

验证属性

东巴文验证属性列表

属性 说明 返回值
willValidate 是否参与验证 boolean
validity 有效性状态对象 ValidityState
validationMessage 验证错误消息 string
checkValidity() 检查有效性 boolean
reportValidity() 检查并报告错误 boolean
setCustomValidity(msg) 设置自定义错误 void

ValidityState对象

东巴文ValidityState属性

属性 说明 触发条件
valueMissing 值缺失 required字段为空
typeMismatch 类型不匹配 email/url格式错误
patternMismatch 模式不匹配 pattern验证失败
tooLong 超出最大长度 超过maxlength
tooShort 小于最小长度 小于minlength
rangeUnderflow 小于最小值 小于min
rangeOverflow 大于最大值 大于max
stepMismatch 步长不匹配 不符合step
badInput 无效输入 无法转换为数值
customError 自定义错误 setCustomValidity设置
valid 是否有效 所有验证通过

验证示例

<form id="myForm">
    <div class="form-group">
        <label for="username">用户名</label>
        <input type="text" id="username" name="username" 
               required minlength="6" maxlength="20"
               pattern="[a-zA-Z][a-zA-Z0-9_]{5,19}">
        <span class="error" id="username-error"></span>
    </div>
    
    <div class="form-group">
        <label for="email">邮箱</label>
        <input type="email" id="email" name="email" required>
        <span class="error" id="email-error"></span>
    </div>
    
    <div class="form-group">
        <label for="age">年龄</label>
        <input type="number" id="age" name="age" min="1" max="120">
        <span class="error" id="age-error"></span>
    </div>
    
    <button type="submit">提交</button>
</form>

<script>
    const form = document.getElementById('myForm');
    
    // 验证用户名
    function validateUsername() {
        const input = document.getElementById('username');
        const error = document.getElementById('username-error');
        
        if (input.validity.valueMissing) {
            error.textContent = '请输入用户名';
            return false;
        } else if (input.validity.tooShort) {
            error.textContent = `用户名至少需要${input.minLength}个字符`;
            return false;
        } else if (input.validity.tooLong) {
            error.textContent = `用户名最多${input.maxLength}个字符`;
            return false;
        } else if (input.validity.patternMismatch) {
            error.textContent = '用户名必须以字母开头,只能包含字母、数字、下划线';
            return false;
        } else {
            error.textContent = '';
            return true;
        }
    }
    
    // 验证邮箱
    function validateEmail() {
        const input = document.getElementById('email');
        const error = document.getElementById('email-error');
        
        if (input.validity.valueMissing) {
            error.textContent = '请输入邮箱地址';
            return false;
        } else if (input.validity.typeMismatch) {
            error.textContent = '请输入有效的邮箱地址';
            return false;
        } else {
            error.textContent = '';
            return true;
        }
    }
    
    // 验证年龄
    function validateAge() {
        const input = document.getElementById('age');
        const error = document.getElementById('age-error');
        
        if (input.validity.rangeUnderflow) {
            error.textContent = `年龄不能小于${input.min}`;
            return false;
        } else if (input.validity.rangeOverflow) {
            error.textContent = `年龄不能大于${input.max}`;
            return false;
        } else {
            error.textContent = '';
            return true;
        }
    }
    
    // 实时验证
    document.getElementById('username').addEventListener('input', validateUsername);
    document.getElementById('email').addEventListener('input', validateEmail);
    document.getElementById('age').addEventListener('input', validateAge);
    
    // 提交验证
    form.addEventListener('submit', function(e) {
        const isValid = validateUsername() && validateEmail() && validateAge();
        
        if (!isValid) {
            e.preventDefault();
        }
    });
</script>

自定义验证消息

setCustomValidity()方法

设置自定义错误消息:

<form id="myForm">
    <div class="form-group">
        <label for="password">密码</label>
        <input type="password" id="password" name="password" required>
        <span class="error" id="password-error"></span>
    </div>
    
    <div class="form-group">
        <label for="confirm-password">确认密码</label>
        <input type="password" id="confirm-password" name="confirm-password" required>
        <span class="error" id="confirm-password-error"></span>
    </div>
    
    <button type="submit">提交</button>
</form>

<script>
    const password = document.getElementById('password');
    const confirmPassword = document.getElementById('confirm-password');
    
    confirmPassword.addEventListener('input', function() {
        if (this.value !== password.value) {
            this.setCustomValidity('两次输入的密码不一致');
        } else {
            this.setCustomValidity('');
        }
    });
    
    password.addEventListener('input', function() {
        if (confirmPassword.value && confirmPassword.value !== this.value) {
            confirmPassword.setCustomValidity('两次输入的密码不一致');
        } else {
            confirmPassword.setCustomValidity('');
        }
    });
</script>

东巴文说明

  • setCustomValidity(''):清除自定义错误
  • setCustomValidity('消息'):设置自定义错误
  • 设置自定义错误后,validity.customErrortrue

禁用验证

novalidate属性

禁用表单验证:

<!-- 禁用整个表单验证 -->
<form novalidate>
    <input type="email" name="email" required>
    <button type="submit">提交</button>
</form>

formnovalidate属性

禁用特定提交按钮的验证:

<form>
    <input type="email" name="email" required>
    
    <!-- 正常提交(带验证) -->
    <button type="submit">提交</button>
    
    <!-- 保存草稿(不验证) -->
    <button type="submit" formnovalidate>保存草稿</button>
</form>

验证样式

CSS伪类

东巴文验证伪类

伪类 说明 使用场景
:valid 验证通过 显示成功样式
:invalid 验证失败 显示错误样式
:required 必填字段 标记必填项
:optional 可选字段 标记可选项
:in-range 在范围内 数字/日期有效
:out-of-range 超出范围 数字/日期无效

样式示例

<style>
    /* 必填字段样式 */
    input:required {
        border-left: 3px solid #f44336;
    }
    
    /* 可选字段样式 */
    input:optional {
        border-left: 3px solid #ccc;
    }
    
    /* 验证通过样式 */
    input:valid:not(:placeholder-shown) {
        border-color: #4CAF50;
    }
    
    input:valid:not(:placeholder-shown) + .valid-icon {
        display: inline;
    }
    
    /* 验证失败样式 */
    input:invalid:not(:placeholder-shown) {
        border-color: #f44336;
    }
    
    input:invalid:not(:placeholder-shown) + .invalid-icon {
        display: inline;
    }
    
    /* 范围验证样式 */
    input[type="number"]:in-range {
        border-color: #4CAF50;
    }
    
    input[type="number"]:out-of-range {
        border-color: #f44336;
    }
</style>

<form>
    <div class="form-group">
        <label for="username">用户名 *</label>
        <input type="text" id="username" name="username" 
               required minlength="6" placeholder="至少6个字符">
        <span class="valid-icon" style="display:none; color:green;"></span>
        <span class="invalid-icon" style="display:none; color:red;"></span>
    </div>
    
    <div class="form-group">
        <label for="email">邮箱 *</label>
        <input type="email" id="email" name="email" required placeholder="请输入邮箱">
    </div>
    
    <div class="form-group">
        <label for="age">年龄</label>
        <input type="number" id="age" name="age" min="1" max="120" placeholder="1-120">
    </div>
    
    <button type="submit">提交</button>
</form>

验证最佳实践

东巴文表单验证法则

法则1:客户端+服务器双重验证

<!-- ✅ 推荐:客户端验证提升体验 -->
<input type="email" name="email" required pattern="[^@]+@[^@]+\.[^@]+">

<!-- 服务器端验证确保安全 -->
<!-- 后端代码示例(伪代码) -->
<!--
if (!validateEmail($_POST['email'])) {
    return error('邮箱格式错误');
}
-->

法则2:提供清晰的错误提示

<!-- ✅ 推荐:明确的错误消息 -->
<input type="tel" name="phone" 
       pattern="[0-9]{11}" 
       title="请输入11位手机号,例如:13800138000">

<!-- ❌ 不推荐:模糊的错误消息 -->
<input type="tel" name="phone" pattern="[0-9]{11}">

法则3:实时验证反馈

<!-- ✅ 推荐:输入时验证 -->
<input type="email" name="email" 
       oninput="validateEmail(this)"
       onblur="validateEmail(this)">

<!-- ❌ 不推荐:只在提交时验证 -->
<form onsubmit="return validateForm()">

法则4:使用合适的验证属性

<!-- ✅ 推荐:使用HTML5验证属性 -->
<input type="email" name="email" required>
<input type="number" name="age" min="1" max="120">

<!-- ❌ 不推荐:全部使用pattern -->
<input type="text" name="email" pattern="[^@]+@[^@]+\.[^@]+">
<input type="text" name="age" pattern="[0-9]+">

法则5:自定义验证消息

<!-- ✅ 推荐:友好的错误提示 -->
<script>
    function validateEmail(input) {
        if (input.validity.valueMissing) {
            input.setCustomValidity('请输入邮箱地址');
        } else if (input.validity.typeMismatch) {
            input.setCustomValidity('请输入有效的邮箱地址,例如:test@example.com');
        } else {
            input.setCustomValidity('');
        }
    }
</script>

学习检验

知识点测试

问题1:以下哪个属性用于设置正则表达式验证?

A. regex B. pattern C. match D. validate

<details> <summary>点击查看答案</summary>

答案:B

东巴文解释pattern属性用于设置正则表达式验证规则。HTML中没有regexmatchvalidate这些属性。

</details>

问题2:以下哪个方法用于设置自定义验证消息?

A. setErrorMessage() B. setCustomValidity() C. setValidation() D. setError()

<details> <summary>点击查看答案</summary>

答案:B

东巴文解释setCustomValidity()方法用于设置自定义验证消息。HTML5验证API中没有setErrorMessage()setValidation()setError()这些方法。

</details>

实践任务

任务:创建一个完整的注册表单,包含以下验证:

  1. 用户名:必填,6-20个字符,字母开头
  2. 邮箱:必填,邮箱格式
  3. 密码:必填,8-32个字符
  4. 确认密码:必须与密码一致
  5. 手机号:必填,11位数字
  6. 年龄:可选,1-120岁
<details> <summary>点击查看参考答案</summary>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>注册表单 - 东巴文</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 20px;
        }
        
        .container {
            background: white;
            padding: 40px;
            border-radius: 10px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
            width: 100%;
            max-width: 500px;
        }
        
        h1 {
            text-align: center;
            color: #333;
            margin-bottom: 30px;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        label {
            display: block;
            margin-bottom: 5px;
            color: #555;
            font-weight: 500;
        }
        
        label .required {
            color: #f44336;
        }
        
        input[type="text"],
        input[type="email"],
        input[type="password"],
        input[type="tel"],
        input[type="number"] {
            width: 100%;
            padding: 12px;
            border: 2px solid #ddd;
            border-radius: 6px;
            font-size: 14px;
            transition: all 0.3s;
        }
        
        input:focus {
            outline: none;
            border-color: #667eea;
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
        }
        
        input:valid:not(:placeholder-shown) {
            border-color: #4CAF50;
        }
        
        input:invalid:not(:placeholder-shown) {
            border-color: #f44336;
        }
        
        .error-message {
            color: #f44336;
            font-size: 12px;
            margin-top: 5px;
            min-height: 18px;
        }
        
        .success-message {
            color: #4CAF50;
            font-size: 12px;
            margin-top: 5px;
        }
        
        .password-strength {
            margin-top: 5px;
            height: 4px;
            background: #ddd;
            border-radius: 2px;
            overflow: hidden;
        }
        
        .password-strength-bar {
            height: 100%;
            width: 0;
            transition: all 0.3s;
        }
        
        .strength-weak { background: #f44336; width: 33%; }
        .strength-medium { background: #ff9800; width: 66%; }
        .strength-strong { background: #4CAF50; width: 100%; }
        
        button {
            width: 100%;
            padding: 14px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            border-radius: 6px;
            font-size: 16px;
            font-weight: 600;
            cursor: pointer;
            transition: transform 0.3s;
        }
        
        button:hover {
            transform: translateY(-2px);
        }
        
        button:active {
            transform: translateY(0);
        }
        
        button:disabled {
            background: #ccc;
            cursor: not-allowed;
            transform: none;
        }
        
        .success-overlay {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0,0,0,0.5);
            align-items: center;
            justify-content: center;
            z-index: 1000;
        }
        
        .success-modal {
            background: white;
            padding: 40px;
            border-radius: 10px;
            text-align: center;
            max-width: 400px;
        }
        
        .success-modal h2 {
            color: #4CAF50;
            margin-bottom: 20px;
        }
        
        .success-modal p {
            color: #666;
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>东巴文注册</h1>
        
        <form id="registerForm">
            <div class="form-group">
                <label for="username">
                    用户名 <span class="required">*</span>
                </label>
                <input type="text" id="username" name="username" 
                       required minlength="6" maxlength="20"
                       pattern="[a-zA-Z][a-zA-Z0-9_]{5,19}"
                       placeholder="字母开头,6-20个字符"
                       autocomplete="username">
                <div class="error-message" id="username-error"></div>
            </div>
            
            <div class="form-group">
                <label for="email">
                    邮箱 <span class="required">*</span>
                </label>
                <input type="email" id="email" name="email" 
                       required
                       placeholder="请输入邮箱地址"
                       autocomplete="email">
                <div class="error-message" id="email-error"></div>
            </div>
            
            <div class="form-group">
                <label for="phone">
                    手机号 <span class="required">*</span>
                </label>
                <input type="tel" id="phone" name="phone" 
                       required pattern="[0-9]{11}"
                       placeholder="请输入11位手机号"
                       autocomplete="tel">
                <div class="error-message" id="phone-error"></div>
            </div>
            
            <div class="form-group">
                <label for="password">
                    密码 <span class="required">*</span>
                </label>
                <input type="password" id="password" name="password" 
                       required minlength="8" maxlength="32"
                       placeholder="8-32个字符"
                       autocomplete="new-password">
                <div class="password-strength">
                    <div class="password-strength-bar" id="password-strength-bar"></div>
                </div>
                <div class="error-message" id="password-error"></div>
            </div>
            
            <div class="form-group">
                <label for="confirmPassword">
                    确认密码 <span class="required">*</span>
                </label>
                <input type="password" id="confirmPassword" name="confirmPassword" 
                       required
                       placeholder="请再次输入密码"
                       autocomplete="new-password">
                <div class="error-message" id="confirmPassword-error"></div>
            </div>
            
            <div class="form-group">
                <label for="age">年龄</label>
                <input type="number" id="age" name="age" 
                       min="1" max="120"
                       placeholder="可选,1-120岁">
                <div class="error-message" id="age-error"></div>
            </div>
            
            <button type="submit" id="submitBtn">注册</button>
        </form>
    </div>
    
    <div class="success-overlay" id="successOverlay">
        <div class="success-modal">
            <h2>✓ 注册成功!</h2>
            <p>欢迎加入东巴文学习社区!</p>
            <button onclick="closeModal()">确定</button>
        </div>
    </div>
    
    <script>
        const form = document.getElementById('registerForm');
        const username = document.getElementById('username');
        const email = document.getElementById('email');
        const phone = document.getElementById('phone');
        const password = document.getElementById('password');
        const confirmPassword = document.getElementById('confirmPassword');
        const age = document.getElementById('age');
        
        // 验证用户名
        function validateUsername() {
            const error = document.getElementById('username-error');
            
            if (username.validity.valueMissing) {
                error.textContent = '请输入用户名';
                return false;
            } else if (username.validity.tooShort) {
                error.textContent = `用户名至少需要${username.minLength}个字符`;
                return false;
            } else if (username.validity.tooLong) {
                error.textContent = `用户名最多${username.maxLength}个字符`;
                return false;
            } else if (username.validity.patternMismatch) {
                error.textContent = '用户名必须以字母开头,只能包含字母、数字、下划线';
                return false;
            } else {
                error.textContent = '';
                return true;
            }
        }
        
        // 验证邮箱
        function validateEmail() {
            const error = document.getElementById('email-error');
            
            if (email.validity.valueMissing) {
                error.textContent = '请输入邮箱地址';
                return false;
            } else if (email.validity.typeMismatch) {
                error.textContent = '请输入有效的邮箱地址';
                return false;
            } else {
                error.textContent = '';
                return true;
            }
        }
        
        // 验证手机号
        function validatePhone() {
            const error = document.getElementById('phone-error');
            
            if (phone.validity.valueMissing) {
                error.textContent = '请输入手机号';
                return false;
            } else if (phone.validity.patternMismatch) {
                error.textContent = '请输入11位手机号';
                return false;
            } else {
                error.textContent = '';
                return true;
            }
        }
        
        // 验证密码
        function validatePassword() {
            const error = document.getElementById('password-error');
            const strengthBar = document.getElementById('password-strength-bar');
            
            if (password.validity.valueMissing) {
                error.textContent = '请输入密码';
                strengthBar.className = 'password-strength-bar';
                return false;
            } else if (password.validity.tooShort) {
                error.textContent = `密码至少需要${password.minLength}个字符`;
                strengthBar.className = 'password-strength-bar';
                return false;
            } else if (password.validity.tooLong) {
                error.textContent = `密码最多${password.maxLength}个字符`;
                strengthBar.className = 'password-strength-bar';
                return false;
            } else {
                error.textContent = '';
                
                // 密码强度检测
                const value = password.value;
                let strength = 0;
                
                if (value.length >= 8) strength++;
                if (/[a-z]/.test(value) && /[A-Z]/.test(value)) strength++;
                if (/[0-9]/.test(value)) strength++;
                if (/[^a-zA-Z0-9]/.test(value)) strength++;
                
                if (strength <= 1) {
                    strengthBar.className = 'password-strength-bar strength-weak';
                } else if (strength <= 2) {
                    strengthBar.className = 'password-strength-bar strength-medium';
                } else {
                    strengthBar.className = 'password-strength-bar strength-strong';
                }
                
                return true;
            }
        }
        
        // 验证确认密码
        function validateConfirmPassword() {
            const error = document.getElementById('confirmPassword-error');
            
            if (confirmPassword.validity.valueMissing) {
                error.textContent = '请再次输入密码';
                confirmPassword.setCustomValidity('请再次输入密码');
                return false;
            } else if (confirmPassword.value !== password.value) {
                error.textContent = '两次输入的密码不一致';
                confirmPassword.setCustomValidity('两次输入的密码不一致');
                return false;
            } else {
                error.textContent = '';
                confirmPassword.setCustomValidity('');
                return true;
            }
        }
        
        // 验证年龄
        function validateAge() {
            const error = document.getElementById('age-error');
            
            if (age.value === '') {
                error.textContent = '';
                return true;
            } else if (age.validity.rangeUnderflow) {
                error.textContent = `年龄不能小于${age.min}`;
                return false;
            } else if (age.validity.rangeOverflow) {
                error.textContent = `年龄不能大于${age.max}`;
                return false;
            } else {
                error.textContent = '';
                return true;
            }
        }
        
        // 实时验证
        username.addEventListener('input', validateUsername);
        email.addEventListener('input', validateEmail);
        phone.addEventListener('input', validatePhone);
        password.addEventListener('input', () => {
            validatePassword();
            if (confirmPassword.value) {
                validateConfirmPassword();
            }
        });
        confirmPassword.addEventListener('input', validateConfirmPassword);
        age.addEventListener('input', validateAge);
        
        // 表单提交
        form.addEventListener('submit', function(e) {
            e.preventDefault();
            
            const isValid = validateUsername() && 
                           validateEmail() && 
                           validatePhone() && 
                           validatePassword() && 
                           validateConfirmPassword() && 
                           validateAge();
            
            if (isValid) {
                // 显示成功提示
                document.getElementById('successOverlay').style.display = 'flex';
            }
        });
        
        function closeModal() {
            document.getElementById('successOverlay').style.display = 'none';
            form.reset();
            document.getElementById('password-strength-bar').className = 'password-strength-bar';
        }
    </script>
</body>
</html>
</details>

东巴文(db-w.cn) - 让编程学习更有趣、更高效!