Skip to content

RadioGroup 单选组 ​

一组互斥的选项,只能选一个。选项少(2–5 个)且需要一眼看全时用它;选项多或空间紧时用 Select。 选项写成子元素 pt-radio,组本身承载受控值、表单与键盘。

基础用法

一组互斥的选项,受控值是选中项的 value。方向键移动即选中、跳过禁用项;Tab 只停在选中项上。

<pt-radio-group value="pro" name="plan" aria-label="套餐">
  <pt-radio value="free">免费版</pt-radio>
  <pt-radio value="pro">专业版</pt-radio>
  <pt-radio value="team" disabled>团队版</pt-radio>
</pt-radio-group>
横向排列

选项短、横向空间够时用 orientation="horizontal",放不下时自动折行。

<pt-radio-group orientation="horizontal" value="week" aria-label="统计周期">
  <pt-radio value="day">按天</pt-radio>
  <pt-radio value="week">按周</pt-radio>
  <pt-radio value="month">按月</pt-radio>
</pt-radio-group>
禁用与出错

整组禁用时每一项都不可选、不可 Tab;invalid 给每个圆点描红并标 aria-invalid。

<pt-radio-group value="a" disabled aria-label="整组禁用">
  <pt-radio value="a">整组禁用且已选</pt-radio>
  <pt-radio value="b">整组禁用</pt-radio>
</pt-radio-group>
<pt-radio-group invalid required aria-label="出错态">
  <pt-radio value="a">必选但没选</pt-radio>
  <pt-radio value="b">另一项</pt-radio>
</pt-radio-group>

受控值 ​

受控值是组上的 value,等于选中那项 pt-radio 的 value;空串表示没有选中。 每个 pt-radio 都要写非空的 value(与 Radix 的 RadioGroupItem 一样是必填),不会回退到标签文字 —— 文案会随语言、框架渲染原地变化,拿它当值会让选中态与提交值失步。缺 value 的项不可选,方向键也会跳过它。 用户点选、方向键、Space 改变选中时组件自己改写 value 并发 ptChange,外部直接赋值不发。 pt-radio 自己不发事件,它的 checked 由组维护,不要手动设置。

ptChange 照常冒泡:单选组不会嵌套单选组,冒泡不会让外层的双向绑定误收内层的事件。

键盘操作 ​

遵循 WAI-ARIA Radio Group 模式:

按键行为
Tab进出整组;只停在选中项上,没有选中项时停在第一个可用项
↓ →移到下一项并选中,到末尾回到第一项;跳过禁用项
↑ ←移到上一项并选中,到开头回到最后一项
Space选中当前聚焦项

横排、竖排下四个方向键都可用;从右到左书写(dir="rtl")时左右对调。

无障碍 ​

组是 role="radiogroup",页面上没有可见的组标题时要给 aria-label(包装层里属性名是 ariaLabelText)。 每一项的 role="radio" 落在影子树里的圆点上,而不是包着标签文字的宿主上 —— radio 的内容在无障碍树里一律按纯展示处理, 包住标签文字的话,文字里的链接、按钮会被读屏吞掉。圆点的可访问名经 aria-labelledby 取插槽里的标签文字,焦点与 Tab 停靠点也在圆点上(宿主 delegatesFocus,对它调 focus() 会落到圆点)。required / invalid / disabled 分别标注 aria-required / aria-invalid / aria-disabled,orientation 标注 aria-orientation。

整行(圆点 + 文字)都是点击区。标签文字里放的链接、按钮点了是在用它们,不会选中这一项。 对 pt-radio 调 click() 等同于点它,所以文字需要和圆点分开摆放时,可以用 Label 的 for 指向它。 这时插槽是空的,圆点的可访问名由 pt-label 的文字给(跨影子边界的关联,见 Label · 无障碍), pt-radio 上不必再写 aria-label。

表单里的值 ​

放在 <form> 里按 name 提交选中项的值。没有选中时提交 null —— 与原生 radio 组一样,整个字段不出现在 FormData 里。required 且未选时表单校验报 valueMissing。表单重置时回到初始值;外层 <fieldset disabled> 会让整组禁用。

API ​

属性

属性Attribute类型默认值说明
ariaLabelTextaria-labelstring | undefined—无障碍名称:原生 HTML 里写 aria-label,React / Vue / Angular 包装层里属性名是 ariaLabelText。 页面上没有可见的组标题时必须给 —— 读屏进入这一组时先念它。
disableddisabledbooleanfalse禁用整组。只反映使用方自己写的值:外层原生 `<fieldset disabled>`、pt-field / pt-field-set 的禁用另经继承通道生效,不改写它
inheritedDisabledinherited-disabledbooleanfalse外层 pt-field / pt-field-set 下发的禁用。内部继承通道:由它们以 attribute 维护,不建议使用方直接写。 有效禁用是 `disabled` 与它的并集;父元素只写这一条、不碰 `disabled`,读 `el.disabled` 得到的始终是使用方自己写的值
inheritedInvalidinherited-invalidbooleanfalse外层 pt-field 下发的出错态。内部继承通道:由 pt-field 维护,不建议使用方直接写。有效出错是 `invalid` 与它的并集
inheritedRequiredinherited-requiredbooleanfalse外层 pt-field 下发的必填。内部继承通道:由 pt-field 维护,不建议使用方直接写。有效必填是 `required` 与它的并集
invalidinvalidbooleanfalse出错态。校验信息由使用方展示,组件只负责视觉、aria-invalid 与表单校验状态(customError)
namenamestring | undefined—提交表单时的字段名
orientationorientation"horizontal" | "vertical"'vertical'排列方向:vertical 纵向一列(默认),horizontal 横向一行、放不下时折行
requiredrequiredbooleanfalse必填:未选时表单校验报 valueMissing,并标注 aria-required
valuevaluestring''选中项的值(对应 `pt-radio` 的 `value`),空串表示没有选中。受控值:与 ptChange 配对

事件

事件detail 类型说明
ptChangestring用户选中了另一项(点击、方向键、Space)后触发,detail 是新的 `value`。 Vue 的 v-model 与 Angular 的 ngModel 绑在它上面。外部直接改 `value` 不触发。

方法

方法说明
refresh() => Promise<void>选项变动(增删 `pt-radio`、改了某项的 value / disabled)后重新同步选中态与 Tab 停靠点。 直接子元素的增删组件自己能察觉;`pt-radio` 改了自身属性时会自己调它,一般不用手动调。

插槽

名称说明
(默认)选项,写 `pt-radio`

可定制的内部元素(::part())

part说明
base排布选项的容器

pt-radio ​

属性

属性Attribute类型默认值说明
ariaLabelTextaria-labelstring | undefined—无障碍名称:原生 HTML 里写 aria-label,React / Vue / Angular 包装层里属性名是 ariaLabelText。 插槽里没有标签文字、也没有 `pt-label` 用 `for` 指向它时必须给。给了它就不再用插槽文字做可访问名; 有 `pt-label` 指向它时以标签文字为准。
checkedcheckedbooleanfalse是否选中。由 pt-radio-group 按它的 `value` 维护,不要手动设置
disableddisabledbooleanfalse禁用这一项:点击、方向键都跳过它,并标注 aria-disabled
groupDisabledgroup-disabledbooleanfalse所在组整体禁用。由 pt-radio-group 维护,不要手动设置
groupInvalidgroup-invalidbooleanfalse所在组处于出错态。由 pt-radio-group 维护,不要手动设置
inheritedDisabledinherited-disabledbooleanfalse外层 pt-field-set 下发的禁用。内部继承通道:由它以 attribute 维护,不建议使用方直接写。 有效禁用是 `disabled` 与它的并集;父元素只写这一条、不碰 `disabled`,读 `el.disabled` 得到的始终是使用方自己写的值
tabStoptab-stopbooleanfalse是否是组的 Tab 停靠点(圆点 tabindex 为 0,否则 -1)。由 pt-radio-group 按 roving tabindex 维护,不要手动设置
valuevaluestring—这一项的值,选中时成为 `pt-radio-group` 的 `value`。必填且不能为空串:缺了这一项不可选,方向键也会跳过它

插槽

名称说明
(默认)标签文字

可定制的内部元素(::part())

part说明
base整行(圆点 + 标签文字)
control圆点外圈
indicator选中时的实心圆点
label标签文字容器

Apache-2.0 协议开源