表单验证

表单验证概述

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

东巴文(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开头

min和max属性

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

<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>

minlength和maxlength属性

限制文本长度:

<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.customError为true

禁用验证

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中没有regex、match、validate这些属性。

</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) - 让编程学习更有趣、更高效!