
Ant Design Radio.Group 互斥单选框组基本用法、配置参数与源码级原理解析【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design导读在 Ant Designantd中单个Radio只是一个可勾选的圆圈真正让多个单选形成「一组互斥选项」的是Radio.Group容器。本指南以 components/radio/demo/radiogroup.md 中「一组互斥的 Radio 配合使用」这一核心语义为骨架完整讲解Radio.Group的受控用法、options声明式配置、按钮形态、禁用与尺寸等全部配置项并结合仓库源码剖析其「受控/非受控状态管理」与「Context 广播选中值」的底层实现。读完本文你将能够熟练使用Radio.Group构建任何互斥选择场景并理解其内部工作机制。一、互斥的本质为什么单选必须放进 Radio.Groupradiogroup.md的说明非常凝练——zh-CN 为「一组互斥的 Radio 配合使用」en-US 为 A group of radio components。这句话点出了 Radio 组件体系中最核心的设计单选互斥不是每个Radio自己实现的而是由外层Radio.Group统一协调的。从 radio.tsx 的源码可以看到单个Radio内部通过React.useContext(RadioGroupContext)读取组上下文并在点击时依次触发自身props.onChange与组上下文中的groupContext.onChangeconst onChange (e: RadioChangeEvent) { props.onChange?.(e); groupContext?.onChange?.(e); };也就是说选中状态是「组」级别的共享状态组内任意一个Radio被点击事件会上报到Radio.Group由组更新当前值再通过 Context 广播给组内所有Radio让它们重新计算各自的checked见 radio.tsxif (groupContext) { radioProps.name groupContext.name; radioProps.onChange onChange; radioProps.checked props.value groupContext.value; radioProps.disabled radioProps.disabled ?? groupContext.disabled; }checked props.value groupContext.value这一行就是「互斥」的底层逻辑同一时刻组内只有一个Radio的value与组当前值相等因此永远只选中一项。二、基本用法受控模式下的一组互斥 Radioradiogroup.md对应的演示代码 components/radio/demo/radiogroup.tsx 给出了最经典、最完整的受控用法这也是本文所有例子的基础。下面完整展开并逐点注释import React, { useState } from react; import type { RadioChangeEvent } from antd; import { Radio } from antd; const App: React.FC () { // 用 useState 维护当前选中的值默认选中 value 为 1 的 Radio const [value, setValue] useState(1); // 组内任意 Radio 被点击都会触发 onChangee.target.value 即被点击项的 value const onChange (e: RadioChangeEvent) { console.log(radio checked, e.target.value); setValue(e.target.value); }; return ( Radio.Group onChange{onChange} value{value} Radio value{1}A/Radio Radio value{2}B/Radio Radio value{3}C/Radio Radio value{4}D/Radio /Radio.Group ); }; export default App;要点说明valueonChange构成受控模式value决定当前选中项onChange在用户点击时被回调。用户点击 A/B/C/D 中任意一项e.target.value就是该项的value将其setValue回去即完成受控更新。value可以是任意类型数字、字符串等只要与各Radio的value一一对应即可本例中value是数字1/2/3/4。互斥效果开箱即用不需要给每个Radio手动设置checked组会统一处理。如果你希望初始有一个默认选中项且后续不关心受控更新可以改用defaultValue详见下文 API 表。相关演示的完整清单仓库 components/radio/demo 目录围绕「Radio 组」场景提供了成体系的演示均可作为实战参考演示文件主题radiogroup.tsx一组互斥 Radio 的基本用法本文主体radiogroup-options.tsx使用options数组声明式渲染选项radiogroup-more.tsx组内嵌入「更多…」输入框等自定义内容radiogroup-with-name.tsx为组内所有 Radio 统一设置原生nameradiobutton.tsx按钮风格的单选组radiobutton-solid.tsx实心solid按钮风格disabled.tsx禁用状态size.tsx三种尺寸切换三、options属性用数组声明式渲染一组选项除了把Radio作为children手写Radio.Group还支持通过options属性声明式渲染代码更简洁也便于从后端数据直接驱动。演示代码 components/radio/demo/radiogroup-options.tsx 展示了全部三种写法import React, { useState } from react; import type { RadioChangeEvent } from antd; import { Radio } from antd; // 写法一纯字符串数组 const plainOptions [Apple, Pear, Orange]; // 写法二对象数组label value可附加 title 等 const options [ { label: Apple, value: Apple }, { label: Pear, value: Pear }, { label: Orange, value: Orange, title: Orange }, ]; // 写法三对象数组 单项 disabled const optionsWithDisabled [ { label: Apple, value: Apple }, { label: Pear, value: Pear }, { label: Orange, value: Orange, disabled: true }, ]; const App: React.FC () { const [value1, setValue1] useState(Apple); const [value2, setValue2] useState(Apple); const [value3, setValue3] useState(Apple); const [value4, setValue4] useState(Apple); const onChange1 ({ target: { value } }: RadioChangeEvent) { console.log(radio1 checked, value); setValue1(value); }; // onChange2 / onChange3 / onChange4 结构相同此处省略 return ( {/* 字符串数组 */} Radio.Group options{plainOptions} onChange{onChange1} value{value1} / br / {/* 对象数组其中一项 disabled */} Radio.Group options{optionsWithDisabled} onChange{onChange2} value{value2} / br / br / {/* 按钮形态outline */} Radio.Group options{options} onChange{onChange3} value{value3} optionTypebutton / br / br / {/* 按钮形态 实心样式 */} Radio.Group options{optionsWithDisabled} onChange{onChange4} value{value4} optionTypebutton buttonStylesolid / / ); }; export default App;options支持的数据形态结合 group.tsx 的源码实现options的解析逻辑非常清晰string | number基本类型数组每一项直接作为该Radio的value和显示文本例如[Apple, Pear, Orange]。对象数组支持以下字段字段类型说明labelReactNode选项显示文本valueany选项值用于互斥比较与onChange回调disabledboolean仅禁用该选项优先级与组级disabled合并见下titlestring选项的原生title提示styleCSSProperties作用于该选项的样式idstring该选项的原生idrequiredboolean该选项的原生required标记源码中对象形态的渲染逻辑group.tsx为return ( Radio key{radio-group-value-options-${option.value}} prefixCls{prefixCls} disabled{option.disabled || disabled} value{option.value} checked{value option.value} title{option.title} style{option.style} id{option.id} required{option.required} {option.label} /Radio );注意disabled{option.disabled || disabled}这行单项disabled与组级disabled是「或」的关系组级禁用后即使单项未声明也会被禁用反之组未禁用时可以通过单项disabled: true单独禁用一个选项如上面的optionsWithDisabled中 Orange 不可选。四、进阶场景按钮形态、禁用、尺寸与自定义内容1. 按钮形态optionTypebutton与实心buttonStylesolid单选组有两种展示形态默认的「圆点 文本」和「按钮」形态。通过optionTypebutton切换为按钮组再配合buttonStyle选择描边outline默认或实心solid样式Radio.Group defaultValuea optionTypebutton buttonStylesolid Radio.Button valueaHangzhou/Radio.Button Radio.Button valuebShanghai/Radio.Button Radio.Button valuecBeijing/Radio.Button /Radio.GroupRadio.Group上设置optionTypebutton时组内Radio会渲染为按钮样式等价地也可以使用复合组件Radio.Button显式声明其实现radioButton.tsx正是通过RadioOptionTypeContextProvider把optionType注入为button。样式切换的底层逻辑在 radio.tsxoptionType button时prefixCls从ant-radio变为ant-radio-button从而命中按钮形态的样式与波纹效果。注意optionType仅在Radio.Group上受支持直接在单个Radio上使用optionType会在开发环境触发 antd 的 usage 警告见 radio.tsx。2. 禁用组级禁用与单项禁用// 整组禁用 Radio.Group defaultValuea disabled Radio valueaA/Radio Radio valuebB/Radio /Radio.Group // 仅禁用一个选项options 写法 Radio.Group defaultValuea options{[{ label: A, value: a }, { label: B, value: b, disabled: true }]} /从源码看disabled有三层来源并依次合并单项props.disabled→ 组上下文groupContext.disabled由Radio.Group的disabled提供→ 全局DisabledContext由ConfigProvider disabled或Form表单项注入见 radio.tsx。3. 尺寸sizeRadio.Group的size接受large/middle/small不传时通过useSize自动继承ConfigProvider的全局size配置group.tsx并生成ant-radio-group-large/middle/small修饰类group.tsx。Radio.Group defaultValuea sizelarge Radio.Button valueaHangzhou/Radio.Button Radio.Button valuebShanghai/Radio.Button /Radio.Group4. 组内嵌入自定义内容动态「更多…」输入框演示 radiogroup-more.tsx 展示了一个实用的组合技巧——当选中「More...」时动态渲染一个输入框const [value, setValue] useState(1); Radio.Group onChange{onChange} value{value} Space directionvertical Radio value{1}Option A/Radio Radio value{2}Option B/Radio Radio value{3}Option C/Radio Radio value{4} More... {value 4 ? Input style{{ width: 100, marginInlineStart: 10 }} / : null} /Radio /Space /Radio.Group由于Radio的children只是普通内容插槽见 radio.tsx 的span{children}/span在组内混入Input、Space等任意内容是完全合法的这为「其他」选项 补充输入框这类常见交互提供了优雅的解法。五、Radio.GroupAPI 速查源自 interface.ts以下属性均定义在 components/radio/interface.ts 的RadioGroupProps中是官方支持的完整配置面属性类型默认值说明valueany-受控值指定当前选中的Radio的valuedefaultValueany-非受控模式下的初始选中值onChange(e: RadioChangeEvent) void-选项变化时的回调e.target.value为新选中值disabledbooleanfalse是否禁用整组sizelarge \| middle \| small继承ConfigProvider组尺寸仅对按钮形态外观有明显影响namestring-为组内所有Radio统一设置原生name便于表单提交与原生互斥兜底options(string \| number \| { label; value; disabled?; title?; style?; id?; required? })[]-以数组声明式渲染选项optionTypedefault \| buttondefault展示形态圆点单选或按钮单选buttonStyleoutline \| solidoutline按钮形态下的样式描边 / 实心idstring-容器的原生idonMouseEnter/onMouseLeave/onFocus/onBlur事件回调-容器级事件透传group.tsx此外Radio.Group容器会自动透传aria-*与data-*属性源码中通过pickAttrs(props, { aria: true, data: true })实现见 group.tsx并原生支持 RTL 布局direction rtl时添加ant-radio-group-rtl类。受控与非受控useMergedState的统一从 group.tsx 可见Radio.Group内部通过useMergedState(props.defaultValue, { value: props.value })管理选中值传了value即为受控模式组值完全由外部驱动只传defaultValue则为非受控模式组内部自维护状态。事件处理onRadioChangegroup.tsx的关键逻辑是const onRadioChange (ev: RadioChangeEvent) { const lastValue value; const val ev.target.value; if (!(value in props)) { setValue(val); // 非受控时内部同步状态 } const { onChange } props; if (onChange val ! lastValue) { onChange(ev); // 仅在选中值真正变化时回调 } };值得注意的细节只有值发生变化val ! lastValue才会触发onChange重复点击当前选中项不会产生冗余回调这与原生 radio 的行为保持一致。六、源码级原理状态如何从「组」广播到「项」理解Radio.Group的互斥机制核心是掌握它基于 React Context 的「单向数据流」链路。仓库中的相关实现文件为components/radio/group.tsx组容器负责状态管理与广播components/radio/context.tsContext 定义RadioGroupContext与RadioOptionTypeContextcomponents/radio/radio.tsx单项消费组上下文components/radio/interface.ts类型定义components/radio/index.tsx复合组件组装Radio.Group、Radio.Button一次完整交互的调用链可以归纳为点击用户点击组内某个Radio底层rc-checkbox触发onChange上报radio.tsx 先触发单项自身的onChange再调用groupContext.onChange(e)把事件交给Radio.Group更新group.tsx 的onRadioChange取出e.target.value在非受控模式下setValue更新组状态受控模式下状态由外部value驱动并在值变化时回调props.onChange广播Radio.Group通过RadioGroupContextProvider把最新的value、disabled、name、optionType和onChange注入 Contextgroup.tsx重算组内每个Radio重新渲染按props.value groupContext.value重新计算自己的checked于是旧选中项取消、新选中项点亮互斥效果达成。同时context.ts 中还定义了独立的RadioOptionTypeContext专门用于把「按钮形态」从Radio.Group传给内部RadioRadio.Button正是通过它注入optionTypebutton实现形态与选中状态的解耦。七、事件对象RadioChangeEventonChange的回调参数RadioChangeEvent定义于 interface.ts结构如下interface RadioChangeEvent { target: RadioChangeEventTarget; // 包含 value、checked、name 等 Radio 属性 stopPropagation: () void; preventDefault: () void; nativeEvent: MouseEvent; }其中target是RadioChangeEventTargetinterface.ts除了RadioProps的全部属性外还额外带有checked: boolean。实际开发中最常用的是e.target.value新选中的值也可以像演示代码那样用解构简写const onChange ({ target: { value } }: RadioChangeEvent) { setValue(value); };八、实践要点与注意事项互斥无需手动checked不要在组内手动给Radio设checked组上下文会自动计算手动设置会与组逻辑冲突。区分value与defaultValue需要外部控制如受表单状态或请求结果驱动时用value onChange仅需初始选中时用defaultValue二者不要混用。optionType只写在Radio.Group上单独写在Radio上会触发开发环境警告按钮形态也可以直接用Radio.Button复合组件。disabled的叠加规则单项disabled、组级disabled、ConfigProvider/Form的全局DisabledContext三者取「或」优先级从内到外依次合并。options与children二选一源码中options存在且非空时优先渲染optionschildren会被忽略group.tsx。原生name的兜底价值通过Radio.Group的name属性统一设置后组内所有Radio共享同一原生name在无 JavaScript 的极端场景下表单提交也能保持单选语义配合Form使用时antd 的FormItemInputContext会自动为Radio添加ant-radio-wrapper-in-form-item修饰类以适配表单项样式。重复点击不触发onChange选中值未变化时回调不会被触发依赖「每次点击都回调」的逻辑需要自行处理。以上内容均可在当前仓库中逐一验证演示代码见 components/radio/demo 目录实现源码见 group.tsx、radio.tsx、radioButton.tsx、context.ts 与 interface.ts。结合这些文件你可以在自己的项目中放心地把Radio.Group用于任何需要互斥单选的场景。【免费下载链接】ant-designAn enterprise-class UI design language and React UI library项目地址: https://gitcode.com/gh_mirrors/ant/ant-design创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考