Switch 开关
import { Switch } from '@apollo-design/ui';开关选择器。
何时使用
- 需要表示开 / 关两种状态,且切换后立即生效(不需要点「确定」)。
- 与复选框的区别:开关的语义是「立即生效的状态」,复选框是「待提交的选择」。
代码演示
基本 #
最简单的用法:defaultChecked 非受控;@change 回调收到 (checked, event)。
不可用 #
disabled 让开关失效;loading 同样会强制失效(内部是 || 判据)。
加载中 #
loading 表示正在加载:把手位置显示一个转圈图标,并强制不可交互。
尺寸 #
size="small" 得到小号开关;size="default" 已废弃(会提示改用 "medium")。
文字和图标 #
checkedChildren / unCheckedChildren 接受字符串、数字或任意节点(含图标)。
语义化样式 #
通过 classNames / styles 自定义三槽(root / content / indicator);两者都支持对象与
函数两种形态,函数形态能拿到合并后的 props(如 size)。
最后一个开关从 ConfigProvider.components.switch 读取根样式和语义配置,切换时函数样式会随当前 checked 更新。
组件 Token #
通过 ConfigProvider.theme.components.Switch 覆盖组件 Token;当前配置会写入开关根元素的 CSS 变量,由静态样式消费。支持主题切换、嵌套覆盖和撤销。
覆盖 trackHeight / trackMinWidth / trackPadding / handleSize / handleBg /
handleShadow 后的效果(把手比轨道大,探出轨道外)。
见 demo/(7 个,覆盖 antd 的主要用户场景)。
API
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| checked | 指定当前是否选中(受控) | boolean |
— |
| defaultChecked | 初始是否选中(非受控) | boolean |
false |
| value | ⚠️ checked 的别名(antd @since 5.12.0) |
boolean |
— |
| defaultValue | ⚠️ defaultChecked 的别名 |
boolean |
— |
| onChange | change 事件的监听器写法(两个参数;disabled 时不触发) |
(checked: boolean, event: MouseEvent | KeyboardEvent) => void |
— |
| onClick | 原生 click 事件监听器;状态从 change / v-model 获取 | (event: MouseEvent) => void |
— |
| checkedChildren | 选中时的内容 | VNodeChild |
— |
| unCheckedChildren | 未选中时的内容 | VNodeChild |
— |
| disabled | 失效状态 | boolean |
— |
| loading | 加载中;⚠️ 会强制失效(|| 判据) |
boolean |
false |
| size | 尺寸;⚠️ 'default' 已废弃(提示改用 'medium') |
'small' | 'medium' | 'middle' | 'default' |
— |
| autoFocus | 自动获取焦点 | boolean |
— |
| title / id / tabIndex | 原生属性(落 <button>) |
— | — |
| class / style | 根元素原生 attrs(不是 Props) | — | — |
| classNames / styles | 语义槽 { root, content, indicator }(对象或函数) |
— | — |
checked 优先于 value;defaultChecked 优先于 defaultValue,默认值只用于初始化。受控交互只提出更新,显示状态由父级回传决定;撤销两个受控值后保留最后已接受的状态。
Slots
| 插槽 | 说明 |
|---|---|
| checkedChildren | 选中内容;存在时优先于同名 prop,包括有意为空的内容 |
| unCheckedChildren | 未选中内容;存在时优先于同名 prop,包括有意为空的内容 |
插槽内容会随当前渲染更新;条件插槽消失时恢复同名 prop。支持文本、数字(含 0)、VNode 和数组。
ConfigProvider
components.switch 支持 SwitchConfig 的 className、style、classNames 和 styles。同一区域的类名拼接,样式按 Provider styles → Provider 根 style → 组件 styles → 原生根 style 合并,后者优先;配置替换和撤销会即时生效。
未指定的 disabled 和 size 分别跟随 componentDisabled、componentSize。全局 large 使用 Switch 的常规 medium 尺寸;显式组件 prop 优先,loading 始终禁用交互。语义函数读取当前解析后的 size 和 disabled。
Events
| 事件 | 说明 | 参数 |
|---|---|---|
| update:checked | v-model:checked 通道(与 onChange 同时发出) |
boolean |
| update:value | v-model:value 通道(别名通道,同上) |
boolean |
| change | 声明的 Vue 语义事件;每次点击或方向键更新时发送一次,disabled 时不发送 |
(checked: boolean, event: MouseEvent | KeyboardEvent) |
| click | 原生按钮点击,含键盘激活;方向键不合成点击 | MouseEvent |
@change 与 onChange 注册同一事件,不会额外监听原生 DOM change。@click 只接收原生 MouseEvent,支持 .stop / .prevent / .once;不再传旧 (checked, event),无兼容层或弃用期。迁移状态读取到 @change 或 v-model:checked。
原生根 style 支持字符串、对象和数组,与语义 root 样式按 Vue 规则合并;调用方样式优先。
原生小写 tabindex / autofocus 同样落在按钮;同时提供时,显式 tabIndex / autoFocus prop 优先。
键盘
| 按键 | 行为 |
|---|---|
ArrowLeft |
置为未选中(disabled 时不生效) |
ArrowRight |
置为选中(disabled 时不生效) |
Space / Enter |
原生 <button> 的激活行为(等价点击) |
方向键使用标准 KeyboardEvent.key 并阻止滚动;Space/Enter 交由按钮原生激活,只产生一次 click 和状态变更。
Ref
| 名称 | 类型 |
|---|---|
| nativeElement | HTMLButtonElement | null |
| focus / blur | (options?: FocusOptions) => void / () => void |
⚠️ antd 的
ref直接是HTMLButtonElement;本仓按组件库惯例暴露对象 (迁移时ref.current.focus()→ref.value.focus())。
Theme(Component Token)
13 个,与 antd 的 ComponentToken 逐字段对齐(CSS 变量形态 --apollo-switch-*)。
| Token | 说明 | 默认值 |
|---|---|---|
| trackHeight | 开关高度 | 22px |
| trackHeightSM | 小号开关高度 | 16px |
| trackMinWidth | 开关最小宽度 | 44px |
| trackMinWidthSM | 小号开关最小宽度 | 28px |
| trackPadding | 开关内边距 | 2px |
| handleBg | 把手背景色 | #fff |
| handleShadow | 把手阴影 | 0 2px 4px 0 rgba(0,35,11,0.2) |
| handleSize | 把手大小 | 18px |
| handleSizeSM | 小号把手大小 | 12px |
| innerMinMargin | 内容区最小边距 | 9px |
| innerMaxMargin | 内容区最大边距 | 24px |
| innerMinMarginSM | 小号内容区最小边距 | 6px |
| innerMaxMarginSM | 小号内容区最大边距 | 18px |
这 13 项通过 ConfigProvider.theme.components.Switch 配置,数字长度自动补 px,也支持 CSS 长度字符串。没有字段覆盖时从当前全局主题派生;嵌套主题只覆盖指定字段,配置替换和撤销会更新现有按钮。旧 D50「组件 Token 不随主题更新」已修正,静态 CSS 仍保留默认值。
<ConfigProvider :theme="{ components: { Switch: { trackHeight: 14, handleSize: 20 } } }">
<Switch aria-label="自定义开关" />
</ConfigProvider>
主题变量先于 Provider 样式、组件语义根样式和原生根 style 合并;可以通过这些根样式覆盖相应 CSS 变量。自定义 prefixCls 时组件变量使用当前前缀;仍须提供对应静态 CSS。
FAQ
禁用时点击会触发吗?
真实用户交互及按钮的原生 .click() 由浏览器抑制,不发 click/change/update。显式 dispatchEvent 仍是普通 DOM 派发:监听器收到原生事件,但不会改变禁用状态或发送 change/update。
value 和 checked 有什么区别?
没有区别 —— value / defaultValue 是 checked / defaultChecked 的别名
(antd 5.12.0 起为表单场景加的)。两者同时传时 checked 优先。