如何使用Ant Design实现卡片式单选按钮(Radio as Cards)功能
antd 实现单选逻辑卡片的两种可落地方案
方案1:父组件统一管控选中状态(灵活度最高)
这是日常开发里最常用的实现方式,核心逻辑非常简单:
- 把当前选中卡片的唯一标识存在所有卡片的共同父组件里,不需要手动写“移除上一个卡片选中态”的代码——每次点击新卡片时,新的选中id会直接覆盖旧值,天然实现同时间仅一个卡片选中的效果。
最小可运行示例:
import { useState } from 'react'; import { Card } from 'antd'; import './index.css'; // 卡片列表模拟数据 const CARD_LIST = [ { id: 1, title: '基础版', content: '适合个人项目使用' }, { id: 2, title: '专业版', content: '适合团队协作场景' }, { id: 3, title: '企业版', content: '支持定制化部署' }, ]; const SelectableCardGroup = () => { // 存储当前选中卡片的id,可根据需求设置默认值 const [selectedId, setSelectedId] = useState(null); return ( <div style={{ display: 'flex', gap: 16 }}> {CARD_LIST.map(item => { const isActive = selectedId === item.id; return ( <Card key={item.id} title={item.title} hoverable // 拼接选中态类名 className={`select-card ${isActive ? 'select-card--active' : ''}`} onClick={() => setSelectedId(item.id)} > {item.content} </Card> ) })} </div> ) }
配套的选中态样式(写在index.css里即可):
.select-card { cursor: pointer; transition: all 0.2s ease; } /* 选中态样式,可根据项目设计规范调整 */ .select-card--active { border-color: #1677ff; background-color: #e6f4ff; box-shadow: 0 2px 8px rgba(22, 119, 255, 0.15); }
方案2:复用Radio.Group原生单选能力(最少自定义代码)
如果卡片是嵌在表单场景下,完全不需要自己写单选管控逻辑——直接把Card嵌套在Radio组件内部,外层用Radio.Group包裹即可。Radio.Group本身就实现了“同一时间仅一个选项选中、自动切换选中态”的核心逻辑,还能天然配合antd的Form.Item做表单值同步、校验,非常省代码。
实现示例:
import { Radio, Card } from 'antd'; const FormSelectableCard = () => { return ( <Radio.Group onChange={(e) => console.log('当前选中值', e.target.value)} > <div style={{ display: 'flex', gap: 16 }}> <Radio value="basic" style={{ width: 280 }}> <Card hoverable>基础版:适合个人项目使用</Card> </Radio> <Radio value="pro" style={{ width: 280 }}> <Card hoverable>专业版:适合团队协作场景</Card> </Radio> </div> </Radio.Group> ) }
常见适配调整
- 需要支持点击已选卡片取消选中:把方案1里的状态更新逻辑改成
setSelectedId(prev => prev === item.id ? null : item.id)即可 - 需要加选中态视觉提示:可以在选中卡片的角落加个CheckCircle图标,用绝对定位悬浮在卡片右上角,不需要改动卡片本身的内部布局
- 需要禁用某张卡片的选中能力:直接给对应卡片加
disabled属性,拦截点击事件即可 - 异步加载卡片列表时,注意等数据加载完成后再匹配初始选中值,避免出现选中态和数据不匹配的问题
内容的提问来源于stack exchange,提问作者Step
相关产品推荐
相关产品推荐

