0
点赞
收藏
分享

微信扫一扫

HTML5 表单元素完全指南:从基础到高级应用

一、HTML5 表单概述

HTML5 为表单开发带来了革命性改进,新增了多种输入类型、属性和验证机制,显著提升了用户体验和开发效率。相比传统表单,HTML5 表单具有以下优势:

  1. 内置验证:减少 JavaScript 验证代码量
  2. 移动端优化:自动适配键盘类型
  3. 语义化元素:更清晰的代码结构
  4. 丰富的 UI 控件:日期选择器、颜色选择器等

二、基础表单结构

1. 标准表单模板

html<!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>
         body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
         .form-group { margin-bottom: 15px; }
         label { display: block; margin-bottom: 5px; font-weight: bold; }
         input, select, textarea { 
             width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; 
             box-sizing: border-box;
         }
         button { 
             background-color: #4CAF50; color: white; padding: 10px 15px; 
             border: none; border-radius: 4px; cursor: pointer; 
         }
         button:hover { background-color: #45a049; }
     </style>
 </head>
 <body>
     <h1>用户注册</h1>
     <form id="registerForm" action="/submit" method="POST">
         <!-- 表单元素将放在这里 -->
         <div class="form-group">
             <button type="submit">提交</button>
         </div>
     </form>
 </body>
 </html>

2. 表单基础属性

html<form 
     action="/api/submit" 
     method="POST" 
     enctype="multipart/form-data" 
     target="_blank"
     autocomplete="on"
     novalidate
 >
     <!-- 表单内容 -->
 </form>

  • action: 表单提交的URL
  • method: HTTP方法(GET/POST)
  • enctype: 编码类型(文件上传需用multipart/form-data
  • target: 响应打开方式(如_blank新窗口)
  • autocomplete: 自动完成功能
  • novalidate: 禁用浏览器验证

三、HTML5 新增输入类型

1. 文本类输入

html<div class="form-group">
     <label for="username">用户名</label>
     <input type="text" id="username" name="username" 
            placeholder="4-16个字符" 
            minlength="4" 
            maxlength="16" 
            required>
 </div>
  
 <div class="form-group">
     <label for="email">电子邮箱</label>
     <input type="email" id="email" name="email" 
            multiple  <!-- 允许输入多个邮箱,用逗号分隔 -->
            pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$">
 </div>
  
 <div class="form-group">
     <label for="password">密码</label>
     <input type="password" id="password" name="password" 
            minlength="8"
            required
            pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" 
            title="必须包含大小写字母和数字">
 </div>
  
 <div class="form-group">
     <label for="search">搜索</label>
     <input type="search" id="search" name="search" 
            results="5"  <!-- 已废弃,建议使用datalist -->
            placeholder="输入关键词...">
 </div>

2. 数字与范围输入

html<div class="form-group">
     <label for="age">年龄</label>
     <input type="number" id="age" name="age" 
            min="18" 
            max="99" 
            step="1"
            value="18">
 </div>
  
 <div class="form-group">
     <label for="price">价格范围</label>
     <input type="range" id="price" name="price" 
            min="0" 
            max="1000" 
            step="10" 
            value="500"
            oninput="rangeValue.value = this.value">
     <output id="rangeValue">500</output> 元
 </div>

3. 日期时间输入

html<div class="form-group">
     <label for="birthday">生日</label>
     <input type="date" id="birthday" name="birthday" 
            min="1900-01-01" 
            max="2023-12-31">
 </div>
  
 <div class="form-group">
     <label for="appt">预约时间</label>
     <input type="datetime-local" id="appt" name="appt" 
            min="2023-01-01T09:00" 
            max="2023-12-31T18:00">
 </div>
  
 <div class="form-group">
     <label for="meeting">会议时间</label>
     <input type="time" id="meeting" name="meeting" 
            min="09:00" 
            max="17:00" 
            step="900"> <!-- 15分钟间隔 -->
 </div>
  
 <div class="form-group">
     <label for="week">选择周数</label>
     <input type="week" id="week" name="week">
 </div>
  
 <div class="form-group">
     <label for="month">选择月份</label>
     <input type="month" id="month" name="month">
 </div>

4. 特殊输入类型

html<div class="form-group">
     <label for="url">个人网站</label>
     <input type="url" id="url" name="url" 
            placeholder="https://example.com">
 </div>
  
 <div class="form-group">
     <label for="tel">电话号码</label>
     <input type="tel" id="tel" name="tel" 
            pattern="[0-9]{3}-[0-9]{8}" 
            placeholder="格式:010-12345678">
 </div>
  
 <div class="form-group">
     <label for="color">选择颜色</label>
     <input type="color" id="color" name="color" 
            value="#ff0000">
 </div>

四、表单控件与元素

1. 选择类控件

html<div class="form-group">
     <label for="country">国家/地区</label>
     <select id="country" name="country" required>
         <option value="">请选择...</option>
         <optgroup label="亚洲">
             <option value="CN">中国</option>
             <option value="JP">日本</option>
             <option value="KR">韩国</option>
         </optgroup>
         <optgroup label="欧洲">
             <option value="UK">英国</option>
             <option value="FR">法国</option>
         </optgroup>
     </select>
 </div>
  
 <div class="form-group">
     <label>兴趣爱好(多选)</label>
     <select name="interests" multiple size="4">
         <option value="sports">运动</option>
         <option value="music">音乐</option>
         <option value="reading">阅读</option>
         <option value="travel">旅行</option>
     </select>
 </div>
  
 <div class="form-group">
     <label>订阅选项</label>
     <div>
         <input type="checkbox" id="subscribe1" name="subscribe" value="newsletter">
         <label for="subscribe1" style="display: inline;">新闻邮件</label>
     </div>
     <div>
         <input type="checkbox" id="subscribe2" name="subscribe" value="promotion" checked>
         <label for="subscribe2" style="display: inline;">促销信息</label>
     </div>
 </div>
  
 <div class="form-group">
     <label>性别</label>
     <div>
         <input type="radio" id="male" name="gender" value="male" checked>
         <label for="male" style="display: inline;">男</label>
     </div>
     <div>
         <input type="radio" id="female" name="gender" value="female">
         <label for="female" style="display: inline;">女</label>
     </div>
     <div>
         <input type="radio" id="other" name="gender" value="other">
         <label for="other" style="display: inline;">其他</label>
     </div>
 </div>

2. 文件上传

html<div class="form-group">
     <label for="avatar">上传头像</label>
     <input type="file" id="avatar" name="avatar" 
            accept="image/*" 
            multiple>
 </div>
  
 <div class="form-group">
     <label for="resume">上传简历</label>
     <input type="file" id="resume" name="resume" 
            accept=".pdf,.doc,.docx,application/msword">
 </div>

3. 文本域与计量器

html<div class="form-group">
     <label for="bio">个人简介</label>
     <textarea id="bio" name="bio" 
               rows="5" 
               maxlength="500"
               placeholder="介绍一下你自己..."></textarea>
     <div style="text-align: right;">
         <small><span id="charCount">0</span>/500</small>
     </div>
 </div>
  
 <div class="form-group">
     <label for="storage">存储空间使用情况</label>
     <meter id="storage" value="65" min="0" max="100" low="30" high="80" optimum="50">
         65%
     </meter>
 </div>
  
 <div class="form-group">
     <label for="confidence">信心指数</label>
     <progress id="confidence" value="70" max="100">70%</progress>
 </div>

五、HTML5 表单验证

1. 内置验证属性

html<div class="form-group">
     <label for="username">用户名</label>
     <input type="text" id="username" name="username" 
            required
            minlength="4"
            maxlength="16"
            pattern="[A-Za-z0-9_]+"
            title="只能包含字母、数字和下划线"
            oninvalid="setCustomValidity('请输入4-16位字母、数字或下划线')"
            oninput="setCustomValidity('')">
 </div>
  
 <div class="form-group">
     <label for="zip">邮政编码</label>
     <input type="text" id="zip" name="zip" 
            pattern="\d{6}" 
            title="6位数字邮政编码">
 </div>

2. JavaScript 验证

html<script>
 document.getElementById('registerForm').addEventListener('submit', function(e) {
     const password = document.getElementById('password').value;
     const confirmPassword = document.getElementById('confirmPassword').value;
     
     if (password !== confirmPassword) {
         alert('两次输入的密码不一致!');
         e.preventDefault(); // 阻止表单提交
     }
     
     // 更复杂的验证可以结合正则表达式
     const phone = document.getElementById('tel').value;
     const phoneRegex = /^1[3-9]\d{9}$/;
     if (!phoneRegex.test(phone)) {
         alert('请输入有效的手机号码');
         e.preventDefault();
     }
 });
  
 // 实时验证示例
 document.getElementById('email').addEventListener('input', function() {
     const email = this.value;
     const feedback = document.getElementById('emailFeedback');
     
     if (!email.includes('@')) {
         feedback.textContent = '邮箱地址必须包含@符号';
         feedback.style.color = 'red';
     } else {
         feedback.textContent = '邮箱格式正确';
         feedback.style.color = 'green';
     }
 });
 </script>

3. 验证样式反馈

css/* 自定义验证样式 */
 input:valid {
     border-color: #4CAF50;
     background-color: #f9fff9;
 }
  
 input:invalid {
     border-color: #f44336;
     background-color: #fff9f9;
 }
  
 input:required:placeholder-shown {
     border-color: #ff9800;
 }
  
 /* 工具提示样式 */
 input + .tooltip {
     visibility: hidden;
     background-color: #555;
     color: #fff;
     padding: 5px 10px;
     border-radius: 4px;
     position: absolute;
     z-index: 1;
 }
  
 input:invalid + .tooltip {
     visibility: visible;
 }

六、高级表单技术

1. 数据列表(自动完成)

html<div class="form-group">
     <label for="browser">选择浏览器</label>
     <input list="browsers" id="browser" name="browser">
     <datalist id="browsers">
         <option value="Chrome">
         <option value="Firefox">
         <option value="Safari">
         <option value="Edge">
         <option value="Opera">
     </datalist>
 </div>
  
 <div class="form-group">
     <label for="city">城市</label>
     <input list="cities" id="city" name="city">
     <datalist id="cities">
         <option value="北京">
         <option value="上海">
         <option value="广州">
         <option value="深圳">
         <option value="杭州">
     </datalist>
 </div>

2. 表单字段集

html<fieldset>
     <legend>联系方式</legend>
     
     <div class="form-group">
         <label for="phone">电话</label>
         <input type="tel" id="phone" name="phone">
     </div>
     
     <div class="form-group">
         <label for="emergency-phone">紧急联系人电话</label>
         <input type="tel" id="emergency-phone" name="emergency_phone">
     </div>
 </fieldset>
  
 <fieldset disabled>
     <legend>管理员设置(禁用)</legend>
     
     <div class="form-group">
         <label for="role">角色</label>
         <select id="role" name="role">
             <option value="admin">管理员</option>
             <option value="editor">编辑</option>
         </select>
     </div>
 </fieldset>

3. 表单按钮

html<div class="form-group">
     <button type="submit">
         <img src="save-icon.png" alt="保存" width="16" height="16">
         保存
     </button>
     
     <button type="reset" style="background-color: #f44336;">
         重置表单
     </button>
     
     <button type="button" onclick="previewForm()">
         预览
     </button>
     
     <input type="image" src="submit-button.png" alt="提交" 
            width="100" height="40"
            formaction="/preview" 
            formmethod="GET"
            formtarget="_blank">
 </div>

七、响应式表单布局

1. CSS Grid 布局

css.form-grid {
     display: grid;
     grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
     gap: 20px;
 }
  
 @media (max-width: 600px) {
     .form-grid {
         grid-template-columns: 1fr;
     }
 }

2. Flexbox 布局

css.form-row {
     display: flex;
     flex-wrap: wrap;
     margin: 0 -10px;
 }
  
 .form-col {
     flex: 1 0 200px;
     margin: 0 10px;
 }
  
 @media (max-width: 480px) {
     .form-col {
         flex: 1 0 100%;
     }
 }

3. 完整响应式表单示例

html<form class="responsive-form">
     <div class="form-row">
         <div class="form-col">
             <label for="first-name">名字</label>
             <input type="text" id="first-name" name="first_name">
         </div>
         <div class="form-col">
             <label for="last-name">姓氏</label>
             <input type="text" id="last-name" name="last_name">
         </div>
     </div>
     
     <div class="form-row">
         <div class="form-col">
             <label for="email">电子邮箱</label>
             <input type="email" id="email" name="email">
         </div>
     </div>
     
     <div class="form-row">
         <div class="form-col">
             <label for="address">地址</label>
             <input type="text" id="address" name="address">
         </div>
     </div>
     
     <div class="form-row">
         <div class="form-col">
             <label for="city">城市</label>
             <input type="text" id="city" name="city">
         </div>
         <div class="form-col">
             <label for="zip">邮政编码</label>
             <input type="text" id="zip" name="zip">
         </div>
     </div>
     
     <div class="form-row">
         <div class="form-col">
             <button type="submit">提交</button>
         </div>
     </div>
 </form>
  
 <style>
 .responsive-form {
     max-width: 800px;
     margin: 0 auto;
     padding: 20px;
 }
  
 .form-row {
     display: flex;
     flex-wrap: wrap;
     margin: 0 -10px 15px;
 }
  
 .form-col {
     flex: 1 0 200px;
     margin: 0 10px;
 }
  
 .form-col label {
     display: block;
     margin-bottom: 5px;
 }
  
 .form-col input {
     width: 100%;
     padding: 8px;
     border: 1px solid #ddd;
     border-radius: 4px;
 }
  
 @media (max-width: 600px) {
     .form-col {
         flex: 1 0 100%;
     }
 }
 </style>

八、表单无障碍访问

1. 最佳实践

html<!-- 1. 正确的标签关联 -->
 <label for="user-id">用户ID:</label>
 <input type="text" id="user-id" name="user_id" 
        aria-describedby="id-help">
 <p id="id-help">用户ID将用于登录系统</p>
  
 <!-- 2. 必填字段标识 -->
 <label for="required-field">
     <span class="required">*</span> 必填字段
 </label>
 <input type="text" id="required-field" required 
        aria-required="true">
  
 <!-- 3. 错误提示 -->
 <div class="form-group">
     <label for="credit-card">信用卡号</label>
     <input type="text" id="credit-card" name="credit_card" 
            aria-invalid="false"
            aria-errormessage="card-error">
     <div id="card-error" class="error-message" role="alert"></div>
 </div>
  
 <!-- 4. 隐藏内容但可供屏幕阅读器读取 -->
 <label for="search">
     搜索
     <span class="sr-only">(输入关键词后按回车)</span>
 </label>
 <input type="search" id="search" name="search">
  
 <style>
 .sr-only {
     position: absolute;
     width: 1px;
     height: 1px;
     padding: 0;
     margin: -1px;
     overflow: hidden;
     clip: rect(0, 0, 0, 0);
     white-space: nowrap;
     border: 0;
 }
  
 .error-message {
     color: #d32f2f;
     font-size: 0.875rem;
     margin-top: 4px;
     display: none;
 }
  
 input[aria-invalid="true"] {
     border-color: #d32f2f;
 }
 </style>
  
 <script>
 const creditCardInput = document.getElementById('credit-card');
 const errorElement = document.getElementById('card-error');
  
 creditCardInput.addEventListener('blur', function() {
     const value = this.value.replace(/\s+/g, '');
     
     if (!/^\d{13,19}$/.test(value)) {
         this.setAttribute('aria-invalid', 'true');
         errorElement.textContent = '请输入有效的信用卡号(13-19位数字)';
         errorElement.style.display = 'block';
     } else {
         this.setAttribute('aria-invalid', 'false');
         errorElement.style.display = 'none';
     }
 });
 </script>

九、表单性能优化

1. 延迟加载非关键表单

html<div class="lazy-form-section" data-src="/partials/address-form.html">
     <!-- 地址表单将通过AJAX加载 -->
     <button type="button" onclick="loadFormSection(this.parentElement)">
         添加地址信息(可选)
     </button>
 </div>
  
 <script>
 function loadFormSection(container) {
     const xhr = new XMLHttpRequest();
     xhr.onload = function() {
         container.innerHTML = this.responseText;
     };
     xhr.open('GET', container.getAttribute('data-src'));
     xhr.send();
 }
 </script>

2. 表单自动保存

html<script>
 // 自动保存表单数据到localStorage
 document.getElementById('registerForm').addEventListener('input', function(e) {
     if (e.target.name) {
         const formData = JSON.parse(localStorage.getItem('formDraft') || '{}');
         formData[e.target.name] = e.target.value;
         localStorage.setItem('formDraft', JSON.stringify(formData));
     }
 });
  
 // 页面加载时恢复数据
 window.addEventListener('DOMContentLoaded', function() {
     const savedData = JSON.parse(localStorage.getItem('formDraft') || '{}');
     for (const [name, value] of Object.entries(savedData)) {
         const element = document.querySelector(`[name="${name}"]`);
         if (element) element.value = value;
     }
 });
  
 // 提交时清除草稿
 document.getElementById('registerForm').addEventListener('submit', function() {
     localStorage.removeItem('formDraft');
 });
 </script>

3. 虚拟键盘优化

html<!-- 为移动设备优化输入模式 -->
 <input type="text" inputmode="numeric" pattern="[0-9]*" 
        placeholder="请输入数字验证码">
  
 <input type="text" inputmode="email" 
        placeholder="电子邮箱">
  
 <input type="text" inputmode="url" 
        placeholder="网址">
  
 <input type="text" inputmode="search" 
        placeholder="搜索...">

html<!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>
         :root {
             --primary-color: #4285f4;
             --error-color: #ea4335;
             --success-color: #34a853;
         }
         
         body {
             font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
             line-height: 1.6;
             color: #333;
             background-color: #f5f5f5;
             margin: 0;
             padding: 20px;
         }
         
         .form-container {
             max-width: 800px;
             margin: 0 auto;
             background: white;
             border-radius: 8px;
             box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
             overflow: hidden;
         }
         
         .form-header {
             background-color: var(--primary-color);
             color: white;
             padding: 20px;
             text-align: center;
         }
         
         .form-steps {
             display: flex;
             justify-content: space-between;
             position: relative;
             margin-bottom: 30px;
             padding: 0 20px;
         }
         
         .form-steps::before {
             content: '';
             position: absolute;
             top: 20px;
             left: 0;
             right: 0;
             height: 2px;
             background-color: #ddd;
             z-index: 1;
         }
         
         .step {
             display: flex;
             flex-direction: column;
             align-items: center;
             position: relative;
             z-index: 2;
         }
         
         .step-number {
             width: 40px;
             height: 40px;
             border-radius: 50%;
             background-color: #ddd;
             color: #999;
             display: flex;
             align-items: center;
             justify-content: center;
             margin-bottom: 5px;
             font-weight: bold;
         }
         
         .step.active .step-number {
             background-color: var(--primary-color);
             color: white;
         }
         
         .step.completed .step-number {
             background-color: var(--success-color);
             color: white;
         }
         
         .step-title {
             font-size: 0.875rem;
             color: #666;
         }
         
         .step.active .step-title {
             color: var(--primary-color);
             font-weight: bold;
         }
         
         .form-body {
             padding: 0 40px 30px;
         }
         
         .form-group {
             margin-bottom: 20px;
         }
         
         .form-group label {
             display: block;
             margin-bottom: 5px;
             font-weight: 600;
         }
         
         .form-control {
             width: 100%;
             padding: 12px;
             border: 1px solid #ddd;
             border-radius: 4px;
             font-size: 1rem;
             box-sizing: border-box;
         }
         
         .form-control:focus {
             border-color: var(--primary-color);
             outline: none;
             box-shadow: 0 0 0 2px rgba(66, 133, 244, 0.2);
         }
         
         .form-control.error {
             border-color: var(--error-color);
         }
         
         .error-message {
             color: var(--error-color);
             font-size: 0.875rem;
             margin-top: 5px;
             display: none;
         }
         
         .form-footer {
             display: flex;
             justify-content: space-between;
             padding: 20px 40px;
             background-color: #f9f9f9;
             border-top: 1px solid #eee;
         }
         
         .btn {
             padding: 12px 24px;
             border: none;
             border-radius: 4px;
             font-size: 1rem;
             font-weight: 600;
             cursor: pointer;
             transition: background-color 0.2s;
         }
         
         .btn-primary {
             background-color: var(--primary-color);
             color: white;
         }
         
         .btn-primary:hover {
             background-color: #3367d6;
         }
         
         .btn-secondary {
             background-color: white;
             color: var(--primary-color);
             border: 1px solid var(--primary-color);
         }
         
         .btn-secondary:hover {
             background-color: #f0f4ff;
         }
         
         .btn:disabled {
             opacity: 0.5;
             cursor: not-allowed;
         }
         
         .hidden {
             display: none;
         }
         
         @media (max-width: 768px) {
             .form-body, .form-footer {
                 padding-left: 20px;
                 padding-right: 20px;
             }
             
             .form-steps {
                 padding: 0 10px;
             }
             
             .step-title {
                 font-size: 0.75rem;
             }
         }
     </style>
 </head>
 <body>
     <div class="form-container">
         <div class="form-header">
             <h1>用户注册</h1>
             <p>创建您的账户以享受更多服务</p>
         </div>
         
         <div class="form-steps">
             <div class="step active" data-step="1">
                 <div class="step-number">1</div>
                 <div class="step-title">基本信息</div>
             </div>
             <div class="step" data-step="2">
                 <div class="step-number">2</div>
                 <div class="step-title">联系方式</div>
             </div>
             <div class="step" data-step="3">
                 <div class="step-number">3</div>
                 <div class="step-title">账户安全</div>
             </div>
         </div>
         
         <form id="multiStepForm" novalidate>
             <!-- 第一步:基本信息 -->
             <div class="form-body" id="step1">
                 <div class="form-group">
                     <label for="firstName">名字</label>
                     <input type="text" class="form-control" id="firstName" name="firstName" required>
                     <div class="error-message" id="firstNameError">请输入您的名字</div>
                 </div>
                 
                 <div class="form-group">
                     <label for="lastName">姓氏</label>
                     <input type="text" class="form-control" id="lastName" name="lastName" required>
                     <div class="error-message" id="lastNameError">请输入您的姓氏</div>
                 </div>
                 
                 <div class="form-group">
                     <label for="gender">性别</label>
                     <select class="form-control" id="gender" name="gender" required>
                         <option value="">请选择</option>
                         <option value="male">男</option>
                         <option value="female">女</option>
                         <option value="other">其他</option>
                     </select>
                     <div class="error-message" id="genderError">请选择性别</div>
                 </div>
                 
                 <div class="form-group">
                     <label>出生日期</label>
                     <div class="form-row">
                         <div class="form-col">
                             <select class="form-control" id="birthYear" name="birthYear" required>
                                 <option value="">年份</option>
                                 <!-- 动态生成年份选项 -->
                             </select>
                         </div>
                         <div class="form-col">
                             <select class="form-control" id="birthMonth" name="birthMonth" required>
                                 <option value="">月份</option>
                                 <!-- 动态生成月份选项 -->
                             </select>
                         </div>
                         <div class="form-col">
                             <select class="form-control" id="birthDay" name="birthDay" required>
                                 <option value="">日期</option>
                                 <!-- 动态生成日期选项 -->
                             </select>
                         </div>
                     </div>
                     <div class="error-message" id="birthDateError">请选择完整的出生日期</div>
                 </div>
             </div>
             
             <!-- 第二步:联系方式 -->
             <div class="form-body hidden" id="step2">
                 <div class="form-group">
                     <label for="email">电子邮箱</label>
                     <input type="email" class="form-control" id="email" name="email" required>
                     <div class="error-message" id="emailError">请输入有效的电子邮箱</div>
                 </div>
                 
                 <div class="form-group">
                     <label for="phone">手机号码</label>
                     <input type="tel" class="form-control" id="phone" name="phone" 
                            pattern="[0-9]{11}" required>
                     <div class="error-message" id="phoneError">请输入11位手机号码</div>
                 </div>
                 
                 <div class="form-group">
                     <label for="country">国家/地区</label>
                     <select class="form-control" id="country" name="country" required>
                         <option value="">请选择</option>
                         <option value="CN">中国</option>
                         <option value="US">美国</option>
                         <option value="JP">日本</option>
                         <option value="UK">英国</option>
                     </select>
                     <div class="error-message" id="countryError">请选择国家/地区</div>
                 </div>
                 
                 <div class="form-group">
                     <label for="address">详细地址</label>
                     <textarea class="form-control" id="address" name="address" rows="3" required></textarea>
                     <div class="error-message" id="addressError">请输入详细地址</div>
                 </div>
             </div>
             
             <!-- 第三步:账户安全 -->
             <div class="form-body hidden" id="step3">
                 <div class="form-group">
                     <label for="username">用户名</label>
                     <input type="text" class="form-control" id="username" name="username" 
                            minlength="4" maxlength="16" required>
                     <div class="error-message" id="usernameError">用户名需4-16个字符</div>
                 </div>
                 
                 <div class="form-group">
                     <label for="password">密码</label>
                     <input type="password" class="form-control" id="password" name="password" 
                            minlength="8" required
                            pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$">
                     <div class="error-message" id="passwordError">
                         密码需至少8个字符,包含大小写字母和数字
                     </div>
                 </div>
                 
                 <div class="form-group">
                     <label for="confirmPassword">确认密码</label>
                     <input type="password" class="form-control" id="confirmPassword" name="confirmPassword" required>
                     <div class="error-message" id="confirmPasswordError">两次输入的密码不一致</div>
                 </div>
                 
                 <div class="form-group">
                     <div style="display: flex; align-items: center;">
                         <input type="checkbox" id="agreeTerms" name="agreeTerms" required>
                         <label for="agreeTerms" style="display: inline; margin-left: 10px; margin-bottom: 0;">
                             我已阅读并同意<a href="#">用户协议</a>和<a href="#">隐私政策</a>
                         </label>
                     </div>
                     <div class="error-message" id="agreeTermsError">必须同意条款才能继续</div>
                 </div>
             </div>
             
             <div class="form-footer">
                 <button type="button" class="btn btn-secondary" id="prevBtn" disabled>上一步</button>
                 <button type="button" class="btn btn-primary" id="nextBtn">下一步</button>
                 <button type="submit" class="btn btn-primary hidden" id="submitBtn">提交注册</button>
             </div>
         </form>
     </div>
  
     <script>
         document.addEventListener('DOMContentLoaded', function() {
             // 初始化步骤
             let currentStep = 1;
             const totalSteps = 3;
             
             // 生成日期选项
             function populateDateSelects() {
                 // 年份(1900-当前年份)
                 const yearSelect = document.getElementById('birthYear');
                 const currentYear = new Date().getFullYear();
                 for (let year = currentYear; year >= 1900; year--) {
                     const option = document.createElement('option');
                     option.value = year;
                     option.textContent = year;
                     yearSelect.appendChild(option);
                 }
                 
                 // 月份
                 const monthSelect = document.getElementById('birthMonth');
                 for (let month = 1; month <= 12; month++) {
                     const option = document.createElement('option');
                     option.value = month;
                     option.textContent = month;
                     monthSelect.appendChild(option);
                 }
                 
                 // 日期(根据选择的年月动态变化)
                 const daySelect = document.getElementById('birthDay');
                 document.getElementById('birthMonth').addEventListener('change', updateDays);
                 document.getElementById('birthYear').addEventListener('change', updateDays);
                 
                 function updateDays() {
                     const selectedYear = parseInt(yearSelect.value);
                     const selectedMonth = parseInt(monthSelect.value);
                     
                     // 清空现有选项
                     daySelect.innerHTML = '<option value="">日期</option>';
                     
                     if (selectedYear && selectedMonth) {
                         const daysInMonth = new Date(selectedYear, selectedMonth, 0).getDate();
                         for (let day = 1; day <= daysInMonth; day++) {
                             const option = document.createElement('option');
                             option.value = day;
                             option.textContent = day;
                             daySelect.appendChild(option);
                         }
                     }
                 }
             }
             
             populateDateSelects();
             
             // 步骤导航
             const prevBtn = document.getElementById('prevBtn');
             const nextBtn = document.getElementById('nextBtn');
             const submitBtn = document.getElementById('submitBtn');
             
             prevBtn.addEventListener('click', function() {
                 if (currentStep > 1) {
                     currentStep--;
                     updateStepView();
                 }
             });
             
             nextBtn.addEventListener('click', function() {
                 if (validateStep(currentStep)) {
                     if (currentStep < totalSteps) {
                         currentStep++;
                         updateStepView();
                     }
                 }
             });
             
             // 更新步骤显示
             function updateStepView() {
                 // 隐藏所有步骤内容
                 for (let i = 1; i <= totalSteps; i++) {
                     document.getElementById(`step${i}`).classList.add('hidden');
                 }
                 
                 // 显示当前步骤内容
                 document.getElementById(`step${currentStep}`).classList.remove('hidden');
                 
                 // 更新步骤指示器
                 document.querySelectorAll('.step').forEach((step, index) => {
                     step.classList.toggle('active', index + 1 === currentStep);
                     step.classList.toggle('completed', index + 1 < currentStep);
                 });
                 
                 // 更新按钮状态
                 prevBtn.disabled = currentStep === 1;
                 
                 if (currentStep === totalSteps) {
                     nextBtn.classList.add('hidden');
                     submitBtn.classList.remove('hidden');
                 } else {
                     nextBtn.classList.remove('hidden');
                     submitBtn.classList.add('hidden');
                 }
             }
             
             // 表单验证
             function validateStep(step) {
                 let isValid = true;
                 
                 // 根据步骤验证不同字段
                 switch (step) {
                     case 1:
                         isValid = validateField('firstName') && 
                                  validateField('lastName') && 
                                  validateField('gender') && 
                                  validateBirthDate();
                         break;
                     case 2:
                         isValid = validateField('email') && 
                                  validateField('phone') && 
                                  validateField('country') && 
                                  validateField('address');
                         break;
                     case 3:
                         isValid =

举报

相关推荐

0 条评论