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

# GridView 开发文档

## 技术架构

### 组件结构

```
GridView/
├── index.tsx              # 组件主入口
├── type.ts                # TypeScript 类型定义
├── index.less             # 组件样式
└── docs/                  # 组件文档
    ├── GridView.md
    ├── GridView.$tab-design.md
    ├── GridView.$tab-dev.md
    └── GridView.$tab-test.md
```

### 技术栈

- **React**: 函数式组件
- **TypeScript**: 完整的类型定义
- **Less**: 样式预处理
- **classNames**: 类名管理工具
- **PisellScrollView**: 内置滚动组件

## 核心实现

### 组件代码

```
import PisellScrollView from '../../PisellScrollView';
import React from 'react';
import classNames from 'classnames';
import './index.less';
import { GridViewProps } from './type';

export type { GridViewProps };

const GridView = (props: GridViewProps) => {
  const { className, style, children } = props;

  const footerClassName = classNames('pisell-grid-pro-view', className);

  return (
    <div className={footerClassName} style={style}>
      <PisellScrollView height="100%" overflow="y">
        {children}
      </PisellScrollView>
    </div>
  );
};

export default GridView;
```

### 设计要点

1. **简洁实现**: 组件逻辑简单，专注于容器功能
2. **样式隔离**: 使用 BEM 命名规范 `pisell-grid-pro-view`
3. **滚动包裹**: 使用 PisellScrollView 处理滚动逻辑
4. **属性透传**: 支持 className 和 style 自定义

## 类型定义

### GridViewProps

```typescript
export interface GridViewProps {
  className?: string; // 自定义类名
  children?: React.ReactNode; // 子元素内容
  style?: React.CSSProperties; // 自定义样式
}
```

### 类型说明

- **className**: 可选，用于添加自定义样式类
- **children**: 可选，支持任意 React 节点
- **style**: 可选，CSSProperties 类型的样式对象

## 依赖关系

### 内部依赖

- `PisellScrollView`: 提供滚动功能的核心组件

### 外部依赖

- `react`: React 核心库
- `classnames`: 类名拼接工具

## 样式实现

### Less 样式

```less
.pisell-grid-pro-view {
  flex: 1;
  overflow: hidden;
  height: 100%;

  // 确保 PisellScrollView 占满容器
  .pisell-scroll-view {
    height: 100%;
  }
}
```

### 样式要点

1. **flex: 1**: 占满父容器剩余空间
2. **overflow: hidden**: 防止内容溢出，由 PisellScrollView 控制滚动
3. **height: 100%**: 确保高度填充

## 扩展开发

### 添加自定义滚动配置

如果需要支持更多滚动配置，可以扩展 props：

```
// type.ts
export interface GridViewProps {
  className?: string;
  children?: React.ReactNode;
  style?: React.CSSProperties;
  scrollProps?: {
    height?: string;
    overflow?: 'x' | 'y' | 'both';
    onScroll?: (e: Event) => void;
  };
}

// index.tsx
const GridView = (props: GridViewProps) => {
  const { className, style, children, scrollProps } = props;

  const footerClassName = classNames('pisell-grid-pro-view', className);

  return (
    <div className={footerClassName} style={style}>
      <PisellScrollView
        height={scrollProps?.height || '100%'}
        overflow={scrollProps?.overflow || 'y'}
        onScroll={scrollProps?.onScroll}
      >
        {children}
      </PisellScrollView>
    </div>
  );
};
```

### 添加加载状态

```
export interface GridViewProps {
  className?: string;
  children?: React.ReactNode;
  style?: React.CSSProperties;
  loading?: boolean;
  loadingComponent?: React.ReactNode;
}

const GridView = (props: GridViewProps) => {
  const {
    className,
    style,
    children,
    loading,
    loadingComponent
  } = props;

  const footerClassName = classNames('pisell-grid-pro-view', className);

  return (
    <div className={footerClassName} style={style}>
      <PisellScrollView height="100%" overflow="y">
        {loading ? (loadingComponent || <Spin />) : children}
      </PisellScrollView>
    </div>
  );
};
```

### 添加空状态

```
export interface GridViewProps {
  className?: string;
  children?: React.ReactNode;
  style?: React.CSSProperties;
  empty?: React.ReactNode;
  isEmpty?: boolean;
}

const GridView = (props: GridViewProps) => {
  const { className, style, children, empty, isEmpty } = props;

  const footerClassName = classNames('pisell-grid-pro-view', className);

  return (
    <div className={footerClassName} style={style}>
      <PisellScrollView height="100%" overflow="y">
        {isEmpty ? empty : children}
      </PisellScrollView>
    </div>
  );
};
```

## 性能优化

### 组件优化建议

1. **使用 memo**: 避免不必要的重渲染

```
import React, { memo } from 'react';

const GridView = memo((props: GridViewProps) => {
  // ... 组件实现
});
```

2. **避免内联函数**: 使用 useCallback 优化回调函数

```
const handleScroll = useCallback((e: Event) => {
  // 滚动处理逻辑
}, []);
```

3. **虚拟滚动**: 大量数据时使用虚拟滚动库

```
import { FixedSizeList } from 'react-window';

const GridView = (props: GridViewProps) => {
  return (
    <div className="pisell-grid-pro-view">
      <FixedSizeList
        height={600}
        itemCount={1000}
        itemSize={35}
      >
        {Row}
      </FixedSizeList>
    </div>
  );
};
```

## 调试技巧

### 查看滚动状态

```
import { useEffect, useRef } from 'react';

const GridView = (props: GridViewProps) => {
  const scrollRef = useRef(null);

  useEffect(() => {
    const element = scrollRef.current;
    if (element) {
      console.log('ScrollHeight:', element.scrollHeight);
      console.log('ClientHeight:', element.clientHeight);
      console.log('ScrollTop:', element.scrollTop);
    }
  }, []);

  return (
    <div ref={scrollRef} className="pisell-grid-pro-view">
      {/* ... */}
    </div>
  );
};
```

### 性能监控

```
import { Profiler } from 'react';

const onRenderCallback = (
  id: string,
  phase: "mount" | "update",
  actualDuration: number,
) => {
  console.log(`${id} (${phase}) took ${actualDuration}ms`);
};

<Profiler id="GridView" onRender={onRenderCallback}>
  <GridView>{children}</GridView>
</Profiler>
```

## 常见问题

### Q: 为什么内容不滚动？

A: 检查以下几点：

1. 父容器是否有明确的高度
2. PisellScrollView 的 overflow 属性是否正确
3. 内容高度是否超过容器高度

### Q: 如何自定义滚动条样式？

A: 可以通过 CSS 覆盖 PisellScrollView 的样式：

```less
.pisell-grid-pro-view {
  .pisell-scroll-view {
    &::-webkit-scrollbar {
      width: 8px;
    }
    &::-webkit-scrollbar-thumb {
      background: #888;
      border-radius: 4px;
    }
  }
}
```

### Q: 如何控制滚动位置？

A: 需要获取 PisellScrollView 的 ref：

```
const scrollRef = useRef<HTMLDivElement>(null);

// 滚动到顶部
scrollRef.current?.scrollTo({ top: 0, behavior: 'smooth' });

// 滚动到底部
scrollRef.current?.scrollTo({
  top: scrollRef.current.scrollHeight,
  behavior: 'smooth'
});
```

## 贡献指南

欢迎提交 Issue 和 Pull Request 来改进这个组件！

提交 PR 前请确保：

1. ✅ 代码符合项目规范
2. ✅ 添加了必要的注释
3. ✅ 更新了相关文档
4. ✅ 通过了单元测试
5. ✅ 保持组件的简洁性和专注性
