跳到正文
山月行
返回

React 组件设计全攻略:15+ 个核心 UI 组件设计模式与最佳实践

发布于

设计一个 Select 组件

<Select value="about" onChange={handleChange} placeholder="请选择">
  <Select.Option value="home">Home</Select.Option>
  <Select.Option value="about">About</Select.Option>
  <Select.Option value="blog">Blog</Select.Option>
</Select>

// 支持多选
<Select mode="multiple" value={['home', 'about']} onChange={handleChange}>
  <Select.Option value="home">Home</Select.Option>
  <Select.Option value="about">About</Select.Option>
  <Select.Option value="blog">Blog</Select.Option>
</Select>

设计要点:

  • 支持受控和非受控模式
  • 支持单选、多选模式
  • 键盘导航支持
  • 虚拟滚动(大数据量场景)

设计一个 Icon 组件

<Icon type="right" />
<Icon type="loading" spin />
<Icon type="heart" style={{ color: 'red', fontSize: '20px' }} />

// 支持自定义图标
<Icon component={CustomSvg} />

设计要点:

  • 支持内置图标库和自定义图标
  • 支持旋转、动画效果
  • 可配置大小、颜色等样式属性

设计一个 Layout 组件

<Layout>
  <Layout.Header>Header</Layout.Header>
  <Layout.Content>
    <Layout.Sider width={200}>Sider</Layout.Sider>
    <Layout.Content>Main Content</Layout.Content>
  </Layout.Content>
  <Layout.Footer>Footer</Layout.Footer>
</Layout>

// 响应式布局
<Layout responsive breakpoints={{ md: 768, lg: 1024 }}>
  <Layout.Sider
    collapsible
    collapsed={collapsed}
    onCollapse={setCollapsed}
  >
    Sidebar
  </Layout.Sider>
  <Layout.Content>Content</Layout.Content>
</Layout>

设计要点:

  • 支持经典的上中下、左中右布局
  • 侧边栏可折叠
  • 响应式设计
  • 灵活的嵌套组合

设计一个 Avatar 组件

<Avatar size="large" src="/user.jpg" />
<Avatar size={64} icon="user" />
<Avatar style={{ backgroundColor: '#87d068' }}>张</Avatar>

// 头像组
<Avatar.Group maxCount={3} size="large">
  <Avatar src="/user1.jpg" />
  <Avatar src="/user2.jpg" />
  <Avatar src="/user3.jpg" />
  <Avatar src="/user4.jpg" />
</Avatar.Group>

设计要点:

  • 支持图片、图标、文字显示
  • 可配置大小、形状(圆形/方形)
  • 头像组支持最大显示数量
  • 图片加载失败时的降级处理

设计一个 Button 组件

<Button type="primary" size="large" onClick={handleClick}>
  Primary Button
</Button>

<Button type="default" loading={isLoading}>
  <Icon type="download" />
  Download
</Button>

<Button type="link" href="/about">
  Link Button
</Button>

// 按钮组
<Button.Group>
  <Button>Left</Button>
  <Button>Middle</Button>
  <Button>Right</Button>
</Button.Group>

设计要点:

  • 多种类型:primary、default、dashed、text、link
  • 支持加载状态、禁用状态
  • 可配置大小、形状
  • 支持图标按钮和按钮组

设计一个 Input 组件

<Input
  placeholder="请输入用户名"
  value={username}
  onChange={(e) => setUsername(e.target.value)}
/>

<Input.Password
  placeholder="请输入密码"
  visibilityToggle
/>

<Input.Search
  placeholder="搜索"
  enterButton
  onSearch={handleSearch}
/>

<Input.TextArea
  rows={4}
  placeholder="请输入描述"
  maxLength={200}
  showCount
/>

设计要点:

  • 支持不同类型:text、password、search、textarea
  • 前缀后缀插槽
  • 字符计数、最大长度限制
  • 清除按钮、密码可见性切换

设计一个 Modal 组件

<Modal
  title="确认删除"
  open={isModalOpen}
  onOk={handleOk}
  onCancel={handleCancel}
  okText="删除"
  cancelText="取消"
  okButtonProps={{ danger: true }}
>
  <p>确定要删除这个项目吗?此操作不可恢复。</p>
</Modal>;

// 函数式调用
Modal.confirm({
  title: "确认删除",
  content: "此操作不可恢复",
  onOk: () => handleDelete(),
});

设计要点:

  • 支持声明式和函数式两种调用方式
  • 可配置标题、内容、按钮文本
  • 支持拖拽、全屏模式
  • 键盘 ESC 关闭、点击遮罩关闭

设计一个 Table 组件

<Table
  dataSource={dataSource}
  columns={[
    {
      title: "姓名",
      dataIndex: "name",
      key: "name",
      sorter: true,
      render: (text, record) => <a>{text}</a>,
    },
    {
      title: "年龄",
      dataIndex: "age",
      key: "age",
      sorter: (a, b) => a.age - b.age,
    },
    {
      title: "操作",
      key: "action",
      render: (text, record) => (
        <Button type="link" onClick={() => handleEdit(record)}>
          编辑
        </Button>
      ),
    },
  ]}
  pagination={{
    current: currentPage,
    pageSize: 10,
    total: total,
    onChange: handlePageChange,
  }}
  rowSelection={{
    selectedRowKeys,
    onChange: setSelectedRowKeys,
  }}
/>

设计要点:

  • 支持排序、筛选、分页
  • 行选择功能
  • 自定义列渲染
  • 固定列、表头
  • 虚拟滚动(大数据量)

设计一个 Tabs 组件

<Tabs activeKey={activeKey} onChange={setActiveKey} type="card">
  <Tabs.TabPane tab="用户管理" key="users">
    <UserList />
  </Tabs.TabPane>
  <Tabs.TabPane tab="角色管理" key="roles">
    <RoleList />
  </Tabs.TabPane>
  <Tabs.TabPane
    tab={<span><Icon type="setting" />设置</span>}
    key="settings"
  >
    <Settings />
  </Tabs.TabPane>
</Tabs>

// 可编辑标签页
<Tabs
  type="editable-card"
  onEdit={(targetKey, action) => {
    if (action === 'add') {
      handleAddTab();
    } else {
      handleRemoveTab(targetKey);
    }
  }}
>
  {tabPanes}
</Tabs>

设计要点:

  • 支持多种样式:line、card、editable-card
  • 标签页可编辑(新增、删除)
  • 支持图标、自定义标签内容
  • 懒加载内容

设计一个 Form 组件

<Form
  form={form}
  layout="vertical"
  onFinish={handleSubmit}
  initialValues={{ username: "", email: "" }}
>
  <Form.Item
    name="username"
    label="用户名"
    rules={[
      { required: true, message: "请输入用户名" },
      { min: 3, message: "用户名至少3个字符" },
    ]}
  >
    <Input placeholder="请输入用户名" />
  </Form.Item>

  <Form.Item
    name="email"
    label="邮箱"
    rules={[
      { required: true, message: "请输入邮箱" },
      { type: "email", message: "邮箱格式不正确" },
    ]}
  >
    <Input placeholder="请输入邮箱" />
  </Form.Item>

  <Form.Item>
    <Button type="primary" htmlType="submit">
      提交
    </Button>
  </Form.Item>
</Form>

设计要点:

  • 字段验证、错误提示
  • 支持同步和异步验证
  • 多种布局方式
  • 字段联动、动态字段

设计一个 Card 组件

<Card
  title="卡片标题"
  extra={<Button type="link">更多</Button>}
  actions={[
    <Icon type="setting" />,
    <Icon type="edit" />,
    <Icon type="ellipsis" />
  ]}
>
  <p>卡片内容</p>
</Card>

<Card
  hoverable
  cover={<img src="/image.jpg" alt="cover" />}
  style={{ width: 300 }}
>
  <Card.Meta
    avatar={<Avatar src="/avatar.jpg" />}
    title="标题"
    description="描述信息"
  />
</Card>

设计要点:

  • 支持标题、额外操作、底部操作
  • 可配置封面图片
  • 悬浮效果
  • 加载状态

设计一个 DatePicker 组件

<DatePicker
  placeholder="选择日期"
  onChange={handleDateChange}
  format="YYYY-MM-DD"
/>

<DatePicker.RangePicker
  placeholder={['开始日期', '结束日期']}
  onChange={handleRangeChange}
/>

<DatePicker
  showTime
  placeholder="选择日期时间"
  format="YYYY-MM-DD HH:mm:ss"
/>

设计要点:

  • 支持日期、日期时间、日期范围选择
  • 可配置日期格式
  • 禁用日期、快捷选择
  • 国际化支持

设计一个 Upload 组件

<Upload
  action="/api/upload"
  listType="text"
  multiple
  onChange={handleUploadChange}
  beforeUpload={beforeUpload}
>
  <Button icon={<Icon type="upload" />}>上传文件</Button>
</Upload>

<Upload
  action="/api/upload"
  listType="picture-card"
  fileList={fileList}
  onPreview={handlePreview}
  onChange={handleChange}
>
  <div>
    <Icon type="plus" />
    <div style={{ marginTop: 8 }}>上传</div>
  </div>
</Upload>

// 拖拽上传
<Upload.Dragger
  action="/api/upload"
  multiple
  onChange={handleChange}
>
  <p><Icon type="inbox" style={{ fontSize: 48 }} /></p>
  <p>点击或拖拽文件到此区域上传</p>
</Upload.Dragger>

设计要点:

  • 支持点击、拖拽上传
  • 多种显示样式:文本、图片、卡片
  • 文件预览、进度显示
  • 上传前校验、自定义上传逻辑

设计一个 Tooltip 组件

<Tooltip title="这是一个提示信息">
  <Button>悬浮显示提示</Button>
</Tooltip>

<Tooltip
  title="自定义内容"
  placement="topLeft"
  trigger="click"
  overlayStyle={{ maxWidth: 300 }}
>
  <span>点击显示提示</span>
</Tooltip>

设计要点:

  • 多种触发方式:hover、click、focus
  • 可配置显示位置
  • 支持自定义样式和内容
  • 自动调整位置避免边界溢出

设计一个 Loading 组件

<Loading spinning={isLoading}>
  <div>加载中的内容</div>
</Loading>

<Loading
  spinning={isLoading}
  tip="数据加载中..."
  size="large"
>
  <Table dataSource={data} columns={columns} />
</Loading>

// 独立的加载指示器
<Loading indicator={<Icon type="loading" spin />} />

设计要点:

  • 支持包裹内容和独立使用
  • 可配置加载文本、大小
  • 自定义加载指示器
  • 延迟显示避免闪烁

设计一个 Pagination 组件

<Pagination
  current={currentPage}
  total={500}
  pageSize={20}
  onChange={handlePageChange}
  showSizeChanger
  showQuickJumper
  showTotal={(total, range) =>
    `第 ${range[0]}-${range[1]} 条/共 ${total} 条`
  }
/>

<Pagination
  simple
  current={currentPage}
  total={100}
  onChange={handlePageChange}
/>

设计要点:

  • 支持完整模式和简单模式
  • 页码跳转、每页条数选择
  • 总数显示、自定义文本
  • 键盘导航支持

分享本文:

上一篇
如何高效及正确地打日志
下一篇
JWT 邮件验证与用户登录系统实战:无状态验证码解决方案详解