D03 后台表单页

2026-10-31 14:430 阅读约 14 分钟HTML

摘要:后台页面由两类结构反复组合:录入表单与数据列表。它们对 HTML 的要求与展示页不同——标签必须准确关联、错误必须可定位、操作必须能用键盘完成。本文给出一个「任务录入 + 任务列表」页面的完整结构,含六类控件、分组标题、错误汇总与表格操作列。
关键词:后台表单,字段分组,数据列表,操作列,键盘操作

所属:frontend/html / D-实战 | 上一篇:D02-文章详情页 | 下一篇:无 | 返回:D00-总结

1 引言

后台页面的使用者每天重复同一套操作,任何一次多余点击都会被放大。结构层面的优化只有三点:字段按语义分组、标签与控件一一关联、列表与表单在同一页面内形成闭环。

本文给出一个可直接改造成真实页面的骨架。范围见表 1-1。

项 本文覆盖 本文不覆盖
表单 六个字段、三个分组、必填与错误汇总 接口提交与状态管理
列表 表格结构、操作列、空状态 分页、排序与筛选(依赖脚本)
可用性 键盘操作、错误播报、autocomplete 视觉密度与主题

2 预备知识

项 要求 核对方式
环境 A02 的本地服务器 能访问 localhost
前置 A07、A06 表单与表格已掌握
前置 C02 校验分层与错误提示已掌握
文件 site/admin.html 与 D01 站点同目录

3 原理与实现

3.1 页面由「录入 → 列表 → 回填」闭环构成

后台页面的三段关系固定,缺一段就需要在页面间跳转,如图 3-1 所示。

flowchart LR
    A["录入表单"] --> B["校验与错误汇总"]
    B -->|"通过"| C["提交"]
    B -->|"不通过"| A
    C --> D["数据列表"]
    D --> E["行内操作:编辑 / 删除"]
    E --> A

图 3-1 录入与列表的闭环

图上可见:编辑操作把列表数据带回表单,因此两处的字段名必须一致,否则回填会丢字段。

3.2 完整结构

<!-- 运行环境:Chrome 130+;site/admin.html -->
<main>
  <h1>任务管理</h1>

  <form id="task-form" novalidate>
    <fieldset>
      <legend>基本信息</legend>

      <p>
        <label for="title">任务标题</label>
        <input id="title" name="title" type="text" required maxlength="60" autocomplete="off" aria-describedby="title-error" />
        <span id="title-error" role="alert"></span>
      </p>

      <p>
        <label for="owner">负责人</label>
        <input id="owner" name="owner" type="text" required autocomplete="name" />
      </p>
    </fieldset>

    <fieldset>
      <legend>计划</legend>

      <p>
        <label for="start">开始日期</label>
        <input id="start" name="start" type="date" required />
      </p>

      <p>
        <label for="level">优先级</label>
        <select id="level" name="level">
          <option value="low">低</option>
          <option value="normal" selected>普通</option>
          <option value="high">高</option>
        </select>
      </p>

      <fieldset>
        <legend>协作方式</legend>
        <label><input type="radio" name="mode" value="solo" checked /> 独立</label>
        <label><input type="radio" name="mode" value="pair" /> 结对</label>
      </fieldset>
    </fieldset>

    <fieldset>
      <legend>备注</legend>
      <p>
        <label for="note">说明</label>
        <textarea id="note" name="note" rows="3" maxlength="200"></textarea>
      </p>
      <p aria-live="polite" id="form-summary"></p>
    </fieldset>

    <p>
      <button type="submit">保存</button>
      <button type="reset">清空</button>
    </p>
  </form>

  <section>
    <h2>任务列表</h2>
    <table>
      <caption>最近 3 条任务</caption>
      <thead>
        <tr>
          <th scope="col">标题</th>
          <th scope="col">负责人</th>
          <th scope="col">优先级</th>
          <th scope="col">操作</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th scope="row">补齐文档链接校验</th>
          <td>李明</td>
          <td>高</td>
          <td><a href="#task-form">编辑</a></td>
        </tr>
        <tr>
          <th scope="row">统一图片尺寸</th>
          <td>王芳</td>
          <td>普通</td>
          <td><a href="#task-form">编辑</a></td>
        </tr>
      </tbody>
    </table>
    <p>共 2 条记录。</p>
  </section>
</main>

<script>
  const form = document.getElementById('task-form');
  const summary = document.getElementById('form-summary');

  form.addEventListener('submit', (event) => {
    event.preventDefault();
    if (!form.checkValidity()) {
      const invalid = form.querySelectorAll(':invalid');
      summary.textContent = `共 ${invalid.length} 项未填写完整。`;
      form.querySelector(':invalid').focus();
      return;
    }
    summary.textContent = '已保存。';
  });
</script>

表单与列表的结构要点见表 3-1。

构件 要求 常见问题
字段分组 fieldset + legend,每组不超过 5 个字段 全表单一个 legend,失去分组意义
标签 每个控件都有 label for 用占位文字代替标签
必填 required + 星号说明 只在标签后加星号,不写约束
错误汇总 aria-live="polite" 区域,报告数量 错误只标红,无文本
表格 caption + thead + th scope 表头用 td 加粗
操作列 每行独立操作,锚点或按钮 操作与行数据无对应关系
空状态 无数据时给出一行说明 空表格仅剩表头

键盘可达性检查见表 3-2。

操作 期望行为 检查方式
字段间移动 Tab 按视觉顺序前进 逐次按 Tab 记录顺序
单选组切换 方向键在同一组内切换 聚焦后按左右键
提交 聚焦按钮后回车即可提交 不使用鼠标
跳回表单 列表中「编辑」可定位到表单首字段 点击后检查焦点位置

4 验证与讨论

  1. 留空标题提交,确认焦点跳到标题字段,汇总区显示未完成项数。
  2. 仅用键盘完成一次录入:Tab 遍历、方向键选优先级、回车提交。
  3. 点击列表中的「编辑」,确认焦点落到表单标题字段。
  4. 用朗读软件检查:legend 是否被播报、错误文本是否与字段关联。
检查项 预期结果 说明
分组播报 进入分组时播报组标题 legend
错误定位 首个错误字段获得焦点 4 节步骤 1
列表语义 播报表头与行标题 th scope
回填闭环 编辑后焦点在表单 锚点指向 #task-form
纯键盘可用 全部操作可完成 表 3-2

本项目五项取舍见表 4-1。

决策点 采用方案 备选方案 不选的理由
表单与列表 同页上下排布 弹层内编辑 同页减少焦点管理复杂度
字段分组 三个 fieldset 无分组平铺 分组利于朗读与视觉扫描
错误提示 字段旁文本 + 顶部汇总 仅弹窗提示 弹窗关闭后无法回看哪项出错
优先级 select 单选组 选项多于三个时下拉更省空间
操作列 锚点链接 按钮 + 脚本 锚点无需脚本即可完成定位

讨论与局限。 本页未包含分页与排序,真实列表需要脚本或服务端支持。另同页编辑在数据量大时会导致页面过长,届时应改为独立编辑页,并保留返回列表的导航。

5 常见问题

现象 原因 处理
点标签文字不聚焦控件 for 与 id 不一致 逐对核对
提交后页面刷新丢失输入 未阻止默认提交行为 脚本中 preventDefault()
单选组可同时选中 组内 name 不同 统一 name,用 value 区分
错误提示不播报 汇总区缺少 aria-live 补 aria-live="polite"
长表单提交后找不到错误位置 未聚焦首个无效字段 focus() 到 :invalid 元素

6 结论

序号 结论 依据
1 后台页面由录入、列表、回填三段闭环构成 图 3-1
2 字段分组与标签关联决定可用性下限 表 3-1
3 表格必须给表头语义,操作列需与行数据对应 表 3-1
4 纯键盘走通一次是必做验收 表 3-2

参考文献

[1] MDN Web Docs · fieldset 与 legend,https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/fieldset(访问于 2026-10-29)
[2] W3C · 表单无障碍实践,https://www.w3.org/WAI/tutorials/forms/(访问于 2026-10-29)

返回文章列表

评论 0

0/2000

还没有评论,快来抢沙发吧~