HTML表单基础

学习目标

  • 掌握HTML表单的基本结构和属性
  • 学会使用各种表单元素
  • 理解表单元素的属性配置
  • 能够创建符合Web标准的表单

HTML表单基础结构

HTML表单由<form>标签包裹,包含各种输入元素。基本的表单结构如下:

<!DOCTYPE html>
<html>
<head>
    <title>用户注册表单</title>
    <meta charset="UTF-8">
</head>
<body>
    <form action="process.php" method="post" enctype="multipart/form-data">
        <!-- 表单元素将在这里 -->
        <input type="submit" value="提交">
    </form>
</body>
</html>

form标签的重要属性

1. action属性

指定表单数据提交的目标URL:

<!-- 提交到同一目录下的process.php文件 -->
<form action="process.php" method="post">

<!-- 提交到完整的URL -->
<form action="https://example.com/api/submit" method="post">

<!-- 提交到当前页面(常用于表单自处理) -->
<form action="" method="post">
<form action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" method="post">

2. method属性

指定HTTP请求方法:

<!-- GET方法:数据通过URL传递,有长度限制,不安全 -->
<form action="search.php" method="get">

<!-- POST方法:数据通过HTTP请求体传递,安全,适合敏感数据 -->
<form action="login.php" method="post">

3. enctype属性

指定表单数据的编码类型:

<!-- 默认值:application/x-www-form-urlencoded -->
<form action="submit.php" method="post" enctype="application/x-www-form-urlencoded">

<!-- 文件上传时必须使用:multipart/form-data -->
<form action="upload.php" method="post" enctype="multipart/form-data">

<!-- 纯文本编码,很少使用 -->
<form action="submit.php" method="post" enctype="text/plain">

4. 其他常用属性

<form action="process.php" method="post"
      target="_blank"           <!-- 在新窗口打开结果 -->
      autocomplete="on"         <!-- 启用自动完成 -->
      novalidate>               <!-- 禁用浏览器验证 -->

常用表单元素

1. 文本输入框

<!-- 单行文本输入 -->
<label for="username">用户名:</label>
<input type="text" id="username" name="username"
       placeholder="请输入用户名"
       maxlength="20"
       required>

<!-- 密码输入框 -->
<label for="password">密码:</label>
<input type="password" id="password" name="password"
       minlength="8"
       required>

<!-- 邮箱输入框(HTML5验证) -->
<label for="email">邮箱:</label>
<input type="email" id="email" name="email"
       placeholder="example@domain.com"
       required>

<!-- 数字输入框 -->
<label for="age">年龄:</label>
<input type="number" id="age" name="age"
       min="1" max="120" step="1">

<!-- 电话号码输入框 -->
<label for="phone">电话:</label>
<input type="tel" id="phone" name="phone"
       pattern="[0-9]{11}"
       placeholder="请输入11位手机号">

2. 文本域

<!-- 多行文本输入 -->
<label for="message">留言:</label>
<textarea id="message" name="message"
          rows="5" cols="40"
          maxlength="500"
          placeholder="请输入您的留言..."
          required></textarea>

3. 单选按钮

<fieldset>
    <legend>性别:</legend>
    <label>
        <input type="radio" name="gender" value="male" required> 男
    </label>
    <label>
        <input type="radio" name="gender" value="female"> 女
    </label>
    <label>
        <input type="radio" name="gender" value="other"> 其他
    </label>
</fieldset>

4. 复选框

<fieldset>
    <legend>兴趣爱好:</legend>
    <label>
        <input type="checkbox" name="hobbies[]" value="reading"> 阅读
    </label>
    <label>
        <input type="checkbox" name="hobbies[]" value="music"> 音乐
    </label>
    <label>
        <input type="checkbox" name="hobbies[]" value="sports"> 运动
    </label>
</fieldset>

5. 下拉选择框

<!-- 单选下拉框 -->
<label for="city">城市:</label>
<select id="city" name="city" required>
    <option value="">请选择城市</option>
    <option value="beijing">北京</option>
    <option value="shanghai">上海</option>
    <option value="guangzhou">广州</option>
    <option value="shenzhen">深圳</option>
</select>

<!-- 多选下拉框 -->
<label for="skills">技能:</label>
<select id="skills" name="skills[]" multiple size="4">
    <option value="php">PHP</option>
    <option value="javascript">JavaScript</option>
    <option value="python">Python</option>
    <option value="java">Java</option>
    <option value="css">CSS</option>
</select>

<!-- 分组下拉框 -->
<label for="province">省份:</label>
<select id="province" name="province">
    <optgroup label="华北地区">
        <option value="beijing">北京</option>
        <option value="tianjin">天津</option>
    </optgroup>
    <optgroup label="华东地区">
        <option value="shanghai">上海</option>
        <option value="jiangsu">江苏</option>
    </optgroup>
</select>

6. 文件上传

<!-- 单文件上传 -->
<label for="avatar">头像:</label>
<input type="file" id="avatar" name="avatar"
       accept="image/*"
       required>

<!-- 多文件上传 -->
<label for="documents">文档:</label>
<input type="file" id="documents" name="documents[]"
       multiple
       accept=".pdf,.doc,.docx">

<!-- 隐藏的文件上传(美观的界面) -->
<div class="file-upload">
    <input type="file" id="fileInput" name="file" style="display: none;">
    <button type="button" onclick="document.getElementById('fileInput').click()">
        选择文件
    </button>
    <span id="fileName">未选择文件</span>
</div>

7. 按钮类型

<!-- 提交按钮 -->
<input type="submit" value="注册">
<button type="submit">注册</button>

<!-- 重置按钮 -->
<input type="reset" value="重置表单">
<button type="reset">重置表单</button>

<!-- 普通按钮 -->
<input type="button" value="普通按钮" onclick="alert('点击了按钮')">
<button type="button" onclick="alert('点击了按钮')">普通按钮</button>

<!-- 图像按钮 -->
<input type="image" src="submit.gif" alt="提交" width="100" height="30">

8. 隐藏字段

<!-- 用于传递不需要用户看到的数据 -->
<input type="hidden" name="user_id" value="<?php echo $user_id; ?>">
<input type="hidden" name="csrf_token" value="<?php echo generate_csrf_token(); ?>">

表单分组和标签

fieldset和legend

<form action="process.php" method="post">
    <fieldset>
        <legend>基本信息</legend>
        <label for="name">姓名:</label>
        <input type="text" id="name" name="name" required>

        <label for="email">邮箱:</label>
        <input type="email" id="email" name="email" required>
    </fieldset>

    <fieldset>
        <legend>联系方式</legend>
        <label for="phone">电话:</label>
        <input type="tel" id="phone" name="phone">

        <label for="address">地址:</label>
        <input type="text" id="address" name="address">
    </fieldset>
</form>

label标签的正确使用

<!-- 方法1:使用for属性关联 -->
<label for="username">用户名:</label>
<input type="text" id="username" name="username">

<!-- 方法2:包裹input元素 -->
<label>
    密码:
    <input type="password" name="password">
</label>

<!-- 方法3:隐藏label(仅用于屏幕阅读器) -->
<label for="search" class="sr-only">搜索:</label>
<input type="search" id="search" name="search" placeholder="搜索...">

HTML5新增特性

1. 新的输入类型

<!-- 日期选择器 -->
<label for="birthdate">出生日期:</label>
<input type="date" id="birthdate" name="birthdate">

<!-- 时间选择器 -->
<label for="time">预约时间:</label>
<input type="time" id="time" name="time">

<!-- 日期时间选择器 -->
<label for="datetime">会议时间:</label>
<input type="datetime-local" id="datetime" name="datetime">

<!-- 月份选择器 -->
<label for="month">月份:</label>
<input type="month" id="month" name="month">

<!-- 周选择器 -->
<label for="week">周:</label>
<input type="week" id="week" name="week">

<!-- 颜色选择器 -->
<label for="color">主题颜色:</label>
<input type="color" id="color" name="color" value="#ff0000">

<!-- URL输入 -->
<label for="website">个人网站:</label>
<input type="url" id="website" name="website" placeholder="https://">

<!-- 范围滑块 -->
<label for="volume">音量:</label>
<input type="range" id="volume" name="volume"
       min="0" max="100" value="50" step="1">
<span id="volumeValue">50</span>

<!-- 搜索框 -->
<label for="search">搜索:</label>
<input type="search" id="search" name="search"
       placeholder="输入搜索关键词..."
       autocomplete="on">

2. 表单验证属性

<!-- 必填字段 -->
<input type="text" name="username" required>

<!-- 最小/最大长度 -->
<input type="text" name="username"
       minlength="3" maxlength="20">

<!-- 最小/最大值 -->
<input type="number" name="age"
       min="18" max="100">

<!-- 步长 -->
<input type="number" name="quantity"
       min="0" max="10" step="0.5">

<!-- 正则表达式验证 -->
<input type="text" name="phone"
       pattern="[0-9]{3}-[0-9]{4}-[0-9]{4}"
       title="格式:xxx-xxxx-xxxx">

完整的用户注册表单示例

<!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;
        }
        input[type="radio"], input[type="checkbox"] {
            width: auto;
            margin-right: 5px;
        }
        .error {
            color: red;
            font-size: 12px;
            margin-top: 5px;
        }
        button {
            background-color: #007bff;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        button:hover {
            background-color: #0056b3;
        }
    </style>
</head>
<body>
    <h1>用户注册</h1>

    <form action="register.php" method="post" id="registrationForm">
        <!-- 基本信息 -->
        <fieldset>
            <legend>基本信息</legend>

            <div class="form-group">
                <label for="username">用户名:</label>
                <input type="text" id="username" name="username"
                       placeholder="请输入用户名"
                       minlength="3" maxlength="20"
                       required>
                <div class="error" id="usernameError"></div>
            </div>

            <div class="form-group">
                <label for="email">邮箱:</label>
                <input type="email" id="email" name="email"
                       placeholder="example@domain.com"
                       required>
                <div class="error" id="emailError"></div>
            </div>

            <div class="form-group">
                <label for="password">密码:</label>
                <input type="password" id="password" name="password"
                       minlength="8"
                       required>
                <div class="error" id="passwordError"></div>
            </div>

            <div class="form-group">
                <label for="confirmPassword">确认密码:</label>
                <input type="password" id="confirmPassword" name="confirmPassword"
                       required>
                <div class="error" id="confirmPasswordError"></div>
            </div>

            <div class="form-group">
                <label>性别:</label>
                <label>
                    <input type="radio" name="gender" value="male" required> 男
                </label>
                <label>
                    <input type="radio" name="gender" value="female"> 女
                </label>
            </div>
        </fieldset>

        <!-- 个人信息 -->
        <fieldset>
            <legend>个人信息</legend>

            <div class="form-group">
                <label for="birthdate">出生日期:</label>
                <input type="date" id="birthdate" name="birthdate">
            </div>

            <div class="form-group">
                <label for="phone">电话:</label>
                <input type="tel" id="phone" name="phone"
                       pattern="[0-9]{11}"
                       placeholder="请输入11位手机号">
            </div>

            <div class="form-group">
                <label for="address">地址:</label>
                <input type="text" id="address" name="address">
            </div>

            <div class="form-group">
                <label for="bio">个人简介:</label>
                <textarea id="bio" name="bio"
                          rows="4"
                          maxlength="200"
                          placeholder="简单介绍一下自己..."></textarea>
            </div>
        </fieldset>

        <!-- 兴趣爱好 -->
        <fieldset>
            <legend>兴趣爱好</legend>

            <div class="form-group">
                <label>请选择您的爱好:</label>
                <div>
                    <label>
                        <input type="checkbox" name="hobbies[]" value="reading"> 阅读
                    </label>
                    <label>
                        <input type="checkbox" name="hobbies[]" value="music"> 音乐
                    </label>
                    <label>
                        <input type="checkbox" name="hobbies[]" value="sports"> 运动
                    </label>
                    <label>
                        <input type="checkbox" name="hobbies[]" value="travel"> 旅行
                    </label>
                    <label>
                        <input type="checkbox" name="hobbies[]" value="photography"> 摄影
                    </label>
                </div>
            </div>
        </fieldset>

        <!-- 头像上传 -->
        <fieldset>
            <legend>头像上传</legend>

            <div class="form-group">
                <label for="avatar">选择头像:</label>
                <input type="file" id="avatar" name="avatar"
                       accept="image/*">
            </div>
        </fieldset>

        <!-- 服务条款 -->
        <div class="form-group">
            <label>
                <input type="checkbox" name="terms" required>
                我已阅读并同意<a href="terms.html">服务条款</a>
            </label>
        </div>

        <!-- 提交按钮 -->
        <div class="form-group">
            <button type="submit">注册</button>
            <button type="reset">重置</button>
        </div>
    </form>

    <script>
        // 简单的客户端验证
        document.getElementById('registrationForm').addEventListener('submit', function(e) {
            let isValid = true;

            // 验证密码匹配
            const password = document.getElementById('password').value;
            const confirmPassword = document.getElementById('confirmPassword').value;
            const confirmError = document.getElementById('confirmPasswordError');

            if (password !== confirmPassword) {
                confirmError.textContent = '密码不匹配';
                isValid = false;
            } else {
                confirmError.textContent = '';
            }

            if (!isValid) {
                e.preventDefault();
            }
        });
    </script>
</body>
</html>

最佳实践

  1. 使用语义化HTML:正确使用label、fieldset等标签
  2. 提供良好的用户体验:清晰的标签、合理的布局、即时反馈
  3. 移动端友好:使用响应式设计和适当的输入类型
  4. 安全性考虑:使用适当的方法和编码类型
  5. 无障碍访问:确保表单对残障用户友好

总结

HTML表单是Web应用程序中用户交互的基础。掌握表单的创建和各种输入元素的使用,是开发高质量Web应用的前提。在下一章中,我们将学习如何处理这些表单数据,包括GET和POST方法的使用。