⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

3.2.1 积木的插槽怎么设计——Props 类型定义

一句话破题

Props 是组件的"接口契约",定义了外部可以传入什么数据、什么格式、是否必填。

核心价值

好的 Props 设计让组件既灵活又安全。TypeScript 的类型系统能在编译时捕获错误,让 AI 生成的代码更可靠,也让你在 Review 时更有把握。

Props 基础

定义组件 Props:

tsx
// 方式一:interface(推荐)
interface ButtonProps {
  label: string           // 必填
  variant?: 'primary' | 'secondary'  // 可选,联合类型
  disabled?: boolean      // 可选
  onClick?: () => void    // 可选,回调函数
}

// 方式二:type
type ButtonProps = {
  label: string
  variant?: 'primary' | 'secondary'
}

// 使用 Props
function Button({ label, variant = 'primary', disabled = false, onClick }: ButtonProps) {
  return (
    <button 
      className={`btn-${variant}`}
      disabled={disabled}
      onClick={onClick}
    >
      {label}
    </button>
  )
}

默认值设置

两种方式设置默认值:

tsx
// 方式一:解构时设置(推荐)
function Card({ title, size = 'medium' }: CardProps) {
  // ...
}

// 方式二:defaultProps(不推荐,已过时)
Card.defaultProps = {
  size: 'medium'
}

children Props

children 是特殊的 prop,用于传递嵌套内容:

tsx
interface CardProps {
  title: string
  children: React.ReactNode  // 可以是任何可渲染内容
}

function Card({ title, children }: CardProps) {
  return (
    <div className="card">
      <h2>{title}</h2>
      <div className="card-body">{children}</div>
    </div>
  )
}

// 使用
<Card title="用户信息">
  <p>姓名:张三</p>
  <p>年龄:25</p>
</Card>

常用 Props 类型

类型用途示例
string文本title: string
number数值count: number
boolean开关disabled?: boolean
'a' | 'b'枚举值size: 'sm' | 'md' | 'lg'
() => void无参回调onClick: () => void
(value: T) => void带参回调onChange: (value: string) => void
React.ReactNode可渲染内容children: React.ReactNode
React.CSSProperties内联样式style?: React.CSSProperties
React.ComponentProps<'button'>继承原生属性继承 button 所有属性

继承原生元素属性

当你的组件是对原生元素的包装时:

tsx
// 继承 button 的所有原生属性
interface ButtonProps extends React.ComponentProps<'button'> {
  variant?: 'primary' | 'secondary'
}

function Button({ variant = 'primary', children, ...rest }: ButtonProps) {
  return (
    <button className={`btn-${variant}`} {...rest}>
      {children}
    </button>
  )
}

// 现在可以使用所有原生 button 属性
<Button variant="primary" type="submit" disabled>
  提交
</Button>

泛型 Props

处理通用组件时使用泛型:

tsx
interface ListProps<T> {
  items: T[]
  renderItem: (item: T) => React.ReactNode
}

function List<T>({ items, renderItem }: ListProps<T>) {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>{renderItem(item)}</li>
      ))}
    </ul>
  )
}

// 使用时自动推断类型
<List 
  items={[{ id: 1, name: '张三' }]} 
  renderItem={(user) => <span>{user.name}</span>}  // user 自动推断为 { id: number, name: string }
/>

AI 协作指南

核心意图:让 AI 帮你设计类型安全的组件接口。

需求定义公式

  • 功能描述:组件需要接收 [数据列表]
  • 交互方式:用户可以 [触发事件]
  • 预期效果:组件根据 props 展示 [不同状态]

关键术语interfacechildrenReact.ReactNodeextends ComponentProps、泛型

交互策略

  1. 先让 AI 列出组件需要的所有 props
  2. 让它定义类型接口
  3. 区分必填和可选
  4. 添加合理的默认值

避坑指南

  1. Props 是只读的:永远不要直接修改 props,需要改变时用 state
  2. 避免过度设计:不要预设太多"以后可能用到"的 props
  3. 回调命名规范:事件回调以 on 开头,如 onClickonChange
  4. 可选 props 记得设默认值:避免 undefined 导致的问题

验收清单

  • [ ] Props 接口定义完整,类型准确
  • [ ] 可选 props 有合理的默认值
  • [ ] 使用 children 实现内容插槽
  • [ ] 复杂组件使用泛型保持类型安全