1. Button 核心属性总览:type、disabled、loading、icon、size
Button(按钮)是组件库中出现频率最高的基础交互元素。一个 Button 实例的行为、外观与状态全部由一组有限且可组合的 API 属性控制。本章将系统拆解 type、disabled、loading、icon、size 五个核心属性的取值边界、作用机制及接入方式。理解这五个属性的语义与协同关系,是后续学习 TextField 及其它表单组件 API 设计的基石。
1.1 属性速查与取值清单
| 属性名 | 类型 | 可选值 | 默认值 | 作用简述 |
|---|---|---|---|---|
type |
string | default primary dashed text link |
default |
定义视觉风格层级 |
disabled |
boolean | true false |
false |
禁用交互与视觉置灰 |
loading |
boolean | true false |
false |
显示加载中状态,禁止二次点击 |
icon |
ReactNode / string | 图标组件名或元素 | — | 在按钮文字前插入图标 |
size |
string | large middle small |
middle |
控制按钮高度与内间距 |
type 与 size 控制“外观骨架”,disabled 与 loading 控制“交互状态”,icon 负责“信息点缀”。它们彼此正交,即修改一个属性不会意外覆盖另一个属性的语义。
1.2 属性逐项解析
1.2.1 type —— 视觉层级的首要区分器
type 决定了按钮在页面中的视觉权重。五种取值对应不同的填充策略与边框规则:
- default:白底灰边框,用于次要操作,如“取消”“返回”。
- primary:品牌色填充,用于页面中最核心的引导操作,如“提交”“确认”。
- dashed:白底虚线边框,常见于“添加”“上传”等拓展性操作。
- text:完全无边框无背景,仅保留文字,用于低干扰的链接式操作。
- link:文字带下划线,外观与超链接一致,用于跳转或触发弹窗。
primary 按钮不应超过两个。link 类型的按钮虽然外观像超链接,但它仍然会触发 onClick 事件且保留按钮语义,不要与原生 <a> 标签混用。
1.2.2 disabled —— 硬性阻断所有用户交互
当 disabled=true 时,按钮的 onClick、onMouseEnter、onFocus 等事件全部被框架阻断,同时组件附加一层灰色遮罩或降低不透明度。浏览器默认行为(如键盘 Tab 聚焦)也会被 pointer-events: none 抑制。
// 禁用状态接入示例(React)
<Button
type="primary"
disabled={!isFormValid}
onClick={handleSubmit}
>
提交订单
</Button>
disabled 是否生效,不要只看视觉灰色,必须确认控制台打印的事件绑定未被触发。推荐在 onClick 回调第一行加 console.log('clicked') 来验证。
1.2.3 loading —— 异步操作的瞬时反馈
loading 状态会替换按钮原有图标或文字左侧为旋转动画,同时自动获得 disabled 效果(防止重复提交)。加载时长通常与后端接口响应时间绑定,前端只需在发起请求时置 true,在 finally 中复位。
// 标准 loading 生命周期管理
const [submitting, setSubmitting] = useState(false);
async function handleConfirm() {
setSubmitting(true);
try {
await api.submitOrder(formData);
} finally {
setSubmitting(false);
}
}
return (
<Button
type="primary"
loading={submitting}
onClick={handleConfirm}
>
确认提交
</Button>
);
1.2.4 icon —— 图形化语义增强
icon 属性接收一个图标组件实例(如 <SearchOutlined />)或图标名称字符串(取决于组件库实现)。图标默认位于文字左侧,部分组件库支持通过 iconPosition 调整到右侧。当只传递 icon 而不传入子元素时,按钮变为纯图标按钮,此时务必保证 aria-label 属性携带文案以支持无障碍。
// 图标按钮最佳实践
<Button
type="default"
icon={<SearchOutlined />}
aria-label="搜索"
/>
// 带文字图标按钮
<Button
type="primary"
icon={<DownloadOutlined />}
>
导出报表
</Button>
1.2.5 size —— 间距系统的横向对齐
size 控制按钮的高度、内边距(padding)和字号。三种规格与设计系统的间距刻度保持一致:large(高度 40px,字号 16px)、middle(高度 32px,字号 14px)、small(高度 24px,字号 12px)。当按钮与其他表单组件(如 Input、Select)并排时,必须使用同一 size 值来保证基线对齐。
1.3 属性协同关系与初始化流程
下面这张 SVG 结构图展示了五属性在 Button 渲染流水线中的处理顺序:type 最先决定样式类名,size 确定尺寸 ,icon 在渲染开始时插入,loading 覆盖图标并触发 disabled,最后 disabled 做最终阻断。
1.4 完整接入示例
以下是一个同时使用五个属性的 Button 示例,涵盖初始化状态、异步加载与禁用降级:
import { Button } from 'your-component-library';
import { DownloadOutlined, LoadingOutlined } from '@ant-design/icons';
import { useState } from 'react';
function ExportPanel() {
const [exporting, setExporting] = useState(false);
const [hasData] = useState(true); // 模拟数据是否为空
return (
<Button
type="primary"
size="large"
icon={exporting ? undefined : <DownloadOutlined />}
loading={exporting}
disabled={!hasData}
onClick={async () => {
setExporting(true);
await fetch('/api/export');
setExporting(false);
}}
>
{exporting ? '导出中…' : '导出数据'}
</Button>
);
}
1.5 样式适配要点
属性变更时 Button 的样式响应链路如下:
type切换 → 组件重新计算 --btn-bg、--btn-border、--btn-color 三个 CSS 变量。size切换 → 组件应用不同的 --btn-height、--btn-padding、--btn-font-size。loading与disabled共用一套 --btn-opacity(通常 0.65)但loading保留旋转动画,disabled移除所有动画。icon的尺寸跟随size自动缩放:large=20px,middle=16px,small=14px。
1.6 常见错误排查清单
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 按钮颜色没有变化 | type 传入了未定义的字符串(如 "success") |
检查 type 取值是否在组件库支持的枚举内 |
| 点击后仍触发事件但视觉已置灰 | disabled 未绑定到组件的 disabled prop,仅修改了样式 |
显式传入 disabled=true,不要只加 CSS class |
| loading 状态下按钮可被多次点击 | 未启用组件库内置的 loading 阻断,或手动覆盖了 pointer-events |
确认 loading prop 生效,不要在父容器覆写 pointer-events: auto |
| 图标与文字间距过大/过小 | 自定义了 gap 或 margin 覆盖了组件默认间距 |
优先使用 --btn-icon-gap 等 CSS 变量调整,避免暴力覆盖 |
| size=small 时按钮文字溢出 | 使用了超长文字或字号未同步缩小 | 控制按钮文案长度,或使用 ellipsis 溢出省略 |
1.7 性能优化微提示
- 避免不必要的重渲染:
type、size在初始化后很少改变,应使用React.memo包裹 Button 或通过状态提升来减少父组件更新导致的按钮重渲染。 - 图标懒加载: 如果按钮隐藏在 Tab 或折叠面板中,图标组件可使用动态
React.lazy加载,减少首屏 JS 体积。 - loading 动画不要用大 JS 库: 大多数组件库的 loading 动画是纯 CSS 实现,不需要额外引入 spinner 库;检查组件 DOM 结构,确认加载动效仅通过
@keyframes完成。 - disabled 状态避免复杂选择器: 框架在
disabled时通常只添加一个.btn-disabled类,CSS 优先级控制在 0-1-1 以内,防止后续覆盖困难。
block、ghost、shape、htmlType)均是在这五个属性之上的扩展与修饰。