# 表格

带圆角边框的数据表：表头底色、行悬停高亮、数字列右对齐。窄屏（≤ 767px）默认变成卡片列表，也可以改成横向滚动。样式部分不需要 JS；加 data-zh-table 后可以点表头排序、用复选框选择行。分页用 data-zh-pager。

**依赖**：`zhaoui.css` 与 `zhaoui.js`（原生 HTML、CSS、JS，不需要框架或 jQuery）。

## 用法

```html
<div class="zh-table-wrap">
  <table class="zh-table">
    <thead><tr><th scope="col">标题</th><th scope="col">状态</th><th scope="col" class="num">阅读</th><th scope="col">操作</th></tr></thead>
    <tbody>
      <tr><td data-label="标题">产品发布会回顾</td><td data-label="状态"><span class="zh-tag success">已发布</span></td><td data-label="阅读" class="num">12,480</td><td data-label="操作"><button class="zh-btn sm text">编辑</button></td></tr>
      <tr><td data-label="标题">季度运营复盘</td><td data-label="状态"><span class="zh-tag warning">待审核</span></td><td data-label="阅读" class="num">980</td><td data-label="操作"><button class="zh-btn sm text">编辑</button></td></tr>
    </tbody>
  </table>
</div>

<!-- 列很多、窄屏也想保持表格：加 zh-table-wrap--scroll -->
<div class="zh-table-wrap zh-table-wrap--scroll" tabindex="0" role="region" aria-label="订单列表（可横向滚动）">
  <table class="zh-table">
    <thead><tr><th scope="col">订单号</th><th scope="col">客户</th><th scope="col">地区</th><th scope="col">渠道</th><th scope="col">状态</th><th scope="col" class="num">金额</th><th scope="col">下单时间</th></tr></thead>
    <tbody>
      <tr><td>20261004-0086</td><td>张三</td><td>上海</td><td>官网</td><td>已发货</td><td class="num">1,286.00</td><td>2026-10-04 15:20</td></tr>
      <tr><td>20261004-0087</td><td>李四</td><td>北京</td><td>小程序</td><td>待发货</td><td class="num">329.00</td><td>2026-10-04 15:42</td></tr>
    </tbody>
  </table>
</div>

<div class="zh-table-wrap">
<table class="zh-table" data-zh-table id="tbl-sel">
  <thead><tr><th class="zh-col-check"><input type="checkbox" data-zh-all aria-label="全选"></th><th data-sort="text">标题</th><th data-sort="number" class="num">阅读量</th><th data-sort="text">更新时间</th></tr></thead>
  <tbody>
    <tr><td class="zh-col-check"><input type="checkbox" data-zh-row aria-label="选择产品发布会回顾"></td><td>产品发布会回顾</td><td class="num">12,480</td><td data-sort-value="2026-10-04T15:20">2 小时前</td></tr>
    <tr><td class="zh-col-check"><input type="checkbox" data-zh-row aria-label="选择季度运营复盘"></td><td>季度运营复盘</td><td class="num">980</td><td data-sort-value="2026-10-04T11:02">6 小时前</td></tr>
    <tr><td class="zh-col-check"><input type="checkbox" data-zh-row aria-label="选择新版设计规范说明"></td><td>新版设计规范说明</td><td class="num">8,326</td><td data-sort-value="2026-10-03T18:45">昨天</td></tr>
  </tbody>
</table>
</div>
```

## 样式类

`zh-table-wrap`、`zh-table`、`zh-table-wrap--scroll`

## 属性

| 属性 | 用在 | 取值 | 说明 |
|---|---|---|---|
| `zh-table-wrap` | 外层 <div>（class） | 里面放 <table class="zh-table"> | 圆角边框与裁切；必须有，圆角靠它 |
| `zh-table` | <table>（class） | 正常的 thead / tbody / tr / th / td | 表格样式 |
| `num` | <th> / <td>（class） | 数字、金额 | 右对齐 |
| `data-label` | 每个 <td> | 该列的名称，如 data-label="状态" | 窄屏变卡片列表时显示在值的左侧；不写则左侧为空 |
| `zh-table-wrap--scroll` | 外层 wrap 上（class） | 加在 zh-table-wrap 上 | 窄屏不变卡片，保持表格并允许横向滚动，适合列很多的后台表格 |
| `data-zh-table` | <table> |  | 开启排序和行选择的行为 |
| `data-sort` | 表头 <th> | text \| number | 该列可排序：表头变成按钮，点击在升序、降序、恢复原顺序之间切换。number 会忽略逗号、百分号和货币符号；空值始终排在最后 |
| `data-sort-value` | 单元格 <td> | 用于排序的值 | 单元格显示的文字不适合排序时（如“2 小时前”）用它指定排序值，如 ISO 时间 |
| `data-sort-mode` | <table> | server | 只触发事件、不在页面里重排，用于服务端排序；你在事件里请求新数据 |
| `data-zh-all` | 表头里的 <input type="checkbox"> |  | 全选框；部分行选中时显示半选状态 |
| `data-zh-row` | 每行里的 <input type="checkbox"> |  | 行选择框；选中的行会加上 is-selected 高亮；加 disabled 的行不参与全选 |
| `zh-col-check` | 选择框所在的 <th>/<td> |  | 把该列收窄到刚好放下复选框 |

## 方法

- `ZhaoUI.table.selected(table)`：返回当前选中的 <tr> 数组
- `ZhaoUI.table.clear(table)`：取消全部选择

## 事件

| 事件 | 触发于 | detail | 说明 |
|---|---|---|---|
| `zh:table-sort` | <table> | { index, key, direction } | 排序变化。direction 为 ascending、descending 或 none；key 取 th 的 data-key，没有就用表头文字 |
| `zh:table-select` | <table> | { rows, count, all } | 选择变化。rows 是选中的 <tr> 数组 |

## 无障碍

- 请保留 <thead> 与 <th scope="col">，读屏靠它们读出列名
- 窄屏卡片模式下表头被移出屏幕但仍可被读屏读到；每个 td 的 data-label 同时给视觉用户字段名
- 行内操作按钮（编辑、删除）要有文字或 aria-label
- 行悬停高亮只是辅助，不要把信息只放在悬停上
- 排序与选择需要自己实现：排序列的 <th> 请加 aria-sort，选择框请有 aria-label
- 可排序的表头里是真正的 <button>，键盘可聚焦、回车切换；当前排序列带 aria-sort
- 每个行选择框都要有 aria-label，如“选择《产品发布会回顾》”；全选框写“全选”
- 排序后读屏不会自动朗读结果；需要时在事件里用 ZhaoUI.message 或 aria-live 区域告知
- 横向滚动的容器（zh-table-wrap--scroll）必须加 tabindex="0"、role="region" 和 aria-label，键盘用户才能用方向键左右滚动

## 常见问题

### 表格是什么？

带圆角边框的数据表：表头底色、行悬停高亮、数字列右对齐。窄屏（≤ 767px）默认变成卡片列表，也可以改成横向滚动。样式部分不需要 JS；加 data-zh-table 后可以点表头排序、用复选框选择行。分页用 data-zh-pager。

### 怎么使用表格？

先在页面里引入 zhaoui.css 和 zhaoui.js（放在 </body> 前，不加 defer），再照本页「用法」里的标记书写；需要用代码控制时，用「方法」里列出的接口。

### 表格有哪些事件？

zh:table-sort（排序变化。direction 为 ascending、descending 或 none；key 取 th 的 data-key，没有就用表头文字）；zh:table-select（选择变化。rows 是选中的 <tr> 数组）。

### 表格有哪些方法？

ZhaoUI.table.selected(table)：返回当前选中的 <tr> 数组；ZhaoUI.table.clear(table)：取消全部选择。

### 表格支持键盘和读屏吗？

请保留 <thead> 与 <th scope="col">，读屏靠它们读出列名；窄屏卡片模式下表头被移出屏幕但仍可被读屏读到；每个 td 的 data-label 同时给视觉用户字段名；行内操作按钮（编辑、删除）要有文字或 aria-label。

### 表格需要依赖框架吗？

不需要。ZhaoUI 是原生 HTML、CSS 和 JavaScript，不依赖 jQuery、Vue 或 React。
