---
title: 开发文档
order: 3
category: atom
---

# PisellBasicGrid 开发文档

## 1. 基本信息

| 项目     | 内容                      |
| -------- | ------------------------- |
| 组件名称 | PisellBasicGrid           |
| 组件版本 | 1.0.0                     |
| 组件分类 | 原子组件 (atom)           |
| 技术栈   | React + TypeScript + Less |
| 依赖组件 | 无外部组件依赖            |

## 2. 组件描述

PisellBasicGrid 是一个基于 Flexbox 的基础布局组件，主要用于控制循环型数据组件的排列方式。它提供了灵活的布局配置能力，是构建复杂布局的基础原子组件。

**核心特点**：

- 基于 Flexbox 实现，兼容性好
- 支持两种渲染模式：children 模式和 dataSource 模式
- 无 UI 样式，仅提供布局能力
- 低代码平台友好

## 3. 需求点罗列

### 3.1 布局功能

- [x] 支持横向/竖向/反向排列 (direction)
- [x] 支持换行/不换行/反向换行 (wrap)
- [x] 支持一行 N 个元素 (columns)，需考虑 gap 影响
- [x] 支持等分模式 (equalWidth)
- [x] 支持间距控制 (gap/rowGap/columnGap)
- [x] 支持主轴对齐 (justify)
- [x] 支持交叉轴对齐 (align)
- [x] 支持多行对齐 (alignContent)

### 3.2 渲染功能

- [x] 支持 children 模式渲染
- [x] 支持 dataSource + renderItem 模式渲染
- [x] 支持 rowKey 自动生成 key
- [x] dataSource 为 undefined 时渲染 children
- [x] dataSource 为空数组时不渲染任何内容

### 3.3 扩展功能

- [x] 支持自定义 className
- [x] 支持自定义 style
- [ ] 响应式支持（预留接口，暂不实现）

## 4. 组件 API

### 4.1 Props 定义

| 属性         | 类型                                           | 默认值       | 必填 | 说明               |
| ------------ | ---------------------------------------------- | ------------ | ---- | ------------------ |
| children     | ReactNode                                      | -            | 否   | 子元素             |
| className    | string                                         | -            | 否   | 自定义类名         |
| style        | CSSProperties                                  | -            | 否   | 自定义样式         |
| direction    | DirectionType                                  | 'horizontal' | 否   | 排列方向           |
| wrap         | WrapType                                       | 'nowrap'     | 否   | 换行控制           |
| columns      | number                                         | -            | 否   | 一行显示的元素个数 |
| equalWidth   | boolean                                        | false        | 否   | 是否等分容器宽度   |
| gap          | number \| string                               | -            | 否   | 统一间距           |
| rowGap       | number \| string                               | -            | 否   | 行间距             |
| columnGap    | number \| string                               | -            | 否   | 列间距             |
| justify      | JustifyType                                    | 'start'      | 否   | 主轴对齐方式       |
| align        | AlignType                                      | 'stretch'    | 否   | 交叉轴对齐方式     |
| alignContent | AlignContentType                               | 'stretch'    | 否   | 多行对齐方式       |
| dataSource   | T[]                                            | -            | 否   | 数据源数组         |
| renderItem   | (item: T, index: number) => ReactNode          | -            | 否   | 渲染函数           |
| rowKey       | string \| ((item: T, index: number) => string) | -            | 否   | 指定唯一 key       |

### 4.2 类型定义

```
// 排列方向类型
type DirectionType = 'horizontal' | 'horizontal-reverse' | 'vertical' | 'vertical-reverse';

// 换行类型
type WrapType = 'nowrap' | 'wrap' | 'wrap-reverse';

// 主轴对齐类型
type JustifyType = 'start' | 'end' | 'center' | 'between' | 'around' | 'evenly';

// 交叉轴对齐类型
type AlignType = 'start' | 'end' | 'center' | 'stretch' | 'baseline';

// 多行对齐类型
type AlignContentType = 'start' | 'end' | 'center' | 'between' | 'around' | 'stretch';
```

## 5. 组件模块拆解

```
PisellBasicGrid/
├── index.tsx                    # 组件导出入口
├── PisellBasicGrid.tsx          # 组件核心实现
├── PisellBasicGrid.less         # 组件样式（仅基础布局样式）
├── types.ts                     # TypeScript 类型定义
├── hooks/
│   └── useGridStyle.ts          # 计算布局样式的 Hook
└── utils/
    └── index.ts                 # 工具函数（gap 转换、key 生成等）
```

### 5.1 模块职责

| 模块                | 职责                                                 |
| ------------------- | ---------------------------------------------------- |
| PisellBasicGrid.tsx | 组件主体逻辑，处理渲染模式判断、子元素渲染           |
| useGridStyle.ts     | 根据 props 计算容器和子元素的样式                    |
| utils/index.ts      | 工具函数：gap 单位转换、rowKey 解析、flex-basis 计算 |

## 6. 组件实现方案

### 6.1 整体架构

```
┌─────────────────────────────────────────────────────────┐
│                    PisellBasicGrid                       │
│  ┌─────────────────────────────────────────────────────┐│
│  │                    Props 解析                        ││
│  │  direction / wrap / columns / gap / justify / ...   ││
│  └─────────────────────────────────────────────────────┘│
│                          ↓                               │
│  ┌─────────────────────────────────────────────────────┐│
│  │               useGridStyle Hook                      ││
│  │  计算容器样式 (containerStyle)                       ││
│  │  计算子元素样式 (itemStyle)                          ││
│  └─────────────────────────────────────────────────────┘│
│                          ↓                               │
│  ┌─────────────────────────────────────────────────────┐│
│  │                 渲染模式判断                          ││
│  │  dataSource !== undefined ? dataSource 模式          ││
│  │                           : children 模式            ││
│  └─────────────────────────────────────────────────────┘│
│                          ↓                               │
│  ┌─────────────────────────────────────────────────────┐│
│  │                   渲染输出                           ││
│  │  <div style={containerStyle}>                       ││
│  │    {items.map(item => <div style={itemStyle}>...)}  ││
│  │  </div>                                             ││
│  └─────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
```

### 6.2 核心逻辑实现

#### 6.2.1 容器样式计算

```
// 方向映射
const directionMap = {
  'horizontal': 'row',
  'horizontal-reverse': 'row-reverse',
  'vertical': 'column',
  'vertical-reverse': 'column-reverse',
};

// 主轴对齐映射
const justifyMap = {
  'start': 'flex-start',
  'end': 'flex-end',
  'center': 'center',
  'between': 'space-between',
  'around': 'space-around',
  'evenly': 'space-evenly',
};

// 交叉轴对齐映射
const alignMap = {
  'start': 'flex-start',
  'end': 'flex-end',
  'center': 'center',
  'stretch': 'stretch',
  'baseline': 'baseline',
};
```

#### 6.2.2 子元素样式计算（columns + gap）

```
// 计算 flex-basis，考虑 gap 影响
const calculateFlexBasis = (columns: number, gap: number | string) => {
  const gapValue = typeof gap === 'number' ? `${gap}px` : gap;
  // 公式：(100% - gap * (N-1)) / N
  return `calc((100% - ${gapValue} * ${columns - 1}) / ${columns})`;
};
```

#### 6.2.3 渲染模式判断

```
// 渲染逻辑
const renderContent = () => {
  // dataSource 为 undefined 时，渲染 children
  if (dataSource === undefined) {
    return children;
  }

  // dataSource 为空数组时，不渲染任何内容
  if (dataSource.length === 0) {
    return null;
  }

  // dataSource 模式渲染
  return dataSource.map((item, index) => {
    const key = getRowKey(item, index, rowKey);
    return (
      <div key={key} style={itemStyle}>
        {renderItem?.(item, index)}
      </div>
    );
  });
};
```

#### 6.2.4 rowKey 解析

```
// 获取 rowKey
const getRowKey = (item: T, index: number, rowKey?: string | ((item: T, index: number) => string)) => {
  if (typeof rowKey === 'function') {
    return rowKey(item, index);
  }
  if (typeof rowKey === 'string' && item && typeof item === 'object') {
    return (item as Record<string, any>)[rowKey];
  }
  return index.toString();
};
```

### 6.3 样式方案

由于组件不包含 UI 样式，仅需要基础的布局样式：

```
.pisell-basic-grid {
  display: flex;
  box-sizing: border-box;

  &-item {
    box-sizing: border-box;
  }
}
```

### 6.4 优先级处理

| 场景                    | 优先级                 | 说明                                     |
| ----------------------- | ---------------------- | ---------------------------------------- |
| columns vs equalWidth   | columns > equalWidth   | 设置 columns 时忽略 equalWidth           |
| dataSource vs children  | dataSource > children  | dataSource !== undefined 时忽略 children |
| gap vs rowGap/columnGap | rowGap/columnGap > gap | 单独设置的间距优先级更高                 |

## 7. 扩展性设计

### 7.1 响应式预留

预留 responsive 属性接口，后续版本可扩展：

```
interface ResponsiveConfig {
  columns?: number;
  gap?: number | string;
  direction?: DirectionType;
}

// 预留属性
responsive?: Partial<Record<'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl', ResponsiveConfig>>;
```

### 7.2 样式扩展

支持通过 className 和 style 进行样式扩展，不限制用户的自定义能力。

### 7.3 渲染扩展

dataSource 模式为后续功能扩展提供基础：

- 虚拟滚动
- 分页加载
- 筛选排序

## 8. 注意事项

1. **columns 计算需考虑 gap**：使用 `calc((100% - gap * (N-1)) / N)` 公式
2. **gap 单位处理**：数字类型默认添加 `px` 单位
3. **key 的生成**：组件内部通过 rowKey 自动生成，用户无需手动设置
4. **性能优化**：使用 useMemo 缓存样式计算结果
5. **类型安全**：使用泛型 `<T>` 确保 dataSource 和 renderItem 类型一致
