---
nav:
  title: 组件
  order: 1
group:
  title: 基础组件
  order: 1
title: PisellDataSourceContainer
order: 1
category: pro
---

# PisellDataSourceContainer 数据源容器

PisellDataSourceContainer 是一个强大的数据源容器组件，为列表页面提供统一的数据管理、操作处理、状态共享和子组件协调能力。

## 设计理念

在后台管理系统中，大量页面都涉及数据的增删改查（CRUD）操作。PisellDataSourceContainer 将这些通用的数据操作能力进行了封装和抽象，提供了以下核心能力:

- **数据源管理**: 统一管理数据源配置，支持动态切换
- **操作处理**: 封装 list、get、create、update、destroy 等常用操作
- **状态共享**: 提供 RefManager 和 SharedState 机制，实现跨组件状态管理
- **子组件协调**: 统一管理 Filter、Table、Pagination、Sort 等子组件的 props
- **表单集成**: 内置 Form 实例，自动处理表单变化并触发数据查询

## 核心功能

### 1. 数据源管理

通过 `DataSourceProvider` 提供数据源上下文，支持:

- 数据源配置
- 数据覆盖（overrideData）
- 额外参数（extraParams）
- 设计模式支持（\_\_designMode）

### 2. 操作处理

通过 `HandleActionsProvider` 提供操作方法:

- **list.onSearch**: 查询数据
- **list.onReset**: 重置查询条件
- **list.onPageChange**: 分页切换
- **get**: 获取单条数据
- **create**: 创建数据
- **update**: 更新数据
- **destroy**: 删除数据

### 3. 引用管理

通过 `RefManagerProvider` 提供:

- **Ref 管理**: 注册、获取、注销组件引用
- **SharedState**: 跨组件共享状态和订阅机制

### 4. 子组件协调

通过 `ChildComponentPropsProvider` 统一管理子组件属性:

- Filter 组件属性
- Table 组件属性
- Pagination 组件属性
- Sort 组件属性
- ColumnsSetting 组件属性
- 等等...

## 基础使用

### 简单列表查询

```
import { PisellDataSourceContainer } from '@pisell/materials';

export default () => {
  return (
    <PisellDataSourceContainer
      dataSource="users" // 数据源表名
      autoRun={{ list: true }} // 自动执行查询
      pagination={true} // 启用分页
    >
      <PisellDataSourceContainer.Table />
      <PisellDataSourceContainer.Pagination />
    </PisellDataSourceContainer>
  );
};
```

### 带筛选条件的列表

```
import { PisellDataSourceContainer } from '@pisell/materials';

export default () => {
  return (
    <PisellDataSourceContainer
      dataSource="products"
      autoRun={{ list: true }}
      pagination={{ pageNumber: 1, pageSize: 20 }}
      childComponentProps={{
        filterComponent: {
          value: {
            quickFilter: [
              { name: 'keyword', label: '关键词', type: 'input' },
              { name: 'status', label: '状态', type: 'select', options: [...] }
            ]
          }
        },
        tableComponent: {
          columns: [
            { title: 'ID', dataIndex: 'id' },
            { title: '名称', dataIndex: 'name' },
            { title: '状态', dataIndex: 'status' }
          ]
        }
      }}
    >
      <PisellDataSourceContainer.Filter />
      <PisellDataSourceContainer.Table />
      <PisellDataSourceContainer.Pagination />
    </PisellDataSourceContainer>
  );
};
```

### 自定义子组件

```
import { PisellDataSourceContainer } from '@pisell/materials';
import useContainerContext from '@pisell/materials/pisellDataSourceContainer/hooks/useContainerContext';

const CustomList = () => {
  const { serverActions } = useContainerContext();
  const { data, loading } = serverActions.list;

  return (
    <div>
      {loading && <div>加载中...</div>}
      {data?.list?.map(item => (
        <div key={item.id}>{item.name}</div>
      ))}
    </div>
  );
};

export default () => {
  return (
    <PisellDataSourceContainer
      dataSource="items"
      autoRun={{ list: true }}
    >
      <CustomList />
    </PisellDataSourceContainer>
  );
};
```

### 使用 HOC 包装组件

```
import { withContainer } from '@pisell/materials/pisellDataSourceContainer/utils/withContainer';

const MyTableComponent = ({ serverActions, refManager, form, ...props }) => {
  const { data, loading, onSearch } = serverActions.list;

  return (
    <div>
      <button onClick={() => onSearch({ keyword: 'test' })}>搜索</button>
      {/* 表格内容 */}
    </div>
  );
};

// 使用 withContainer 包装组件
const MyTable = withContainer(MyTableComponent, 'tableComponent');

export default () => {
  return (
    <PisellDataSourceContainer dataSource="users" autoRun={{ list: true }}>
      <MyTable />
    </PisellDataSourceContainer>
  );
};
```

### RefManager 使用示例

```
import { PisellDataSourceContainer } from '@pisell/materials';
import useContainerContext from '@pisell/materials/pisellDataSourceContainer/hooks/useContainerContext';
import { useEffect } from 'react';

const ComponentA = () => {
  const { refManager } = useContainerContext();

  useEffect(() => {
    // 订阅共享状态
    const unsubscribe = refManager.subscribeSharedState('selectedIds', (ids) => {
      console.log('选中的 IDs:', ids);
    });

    return () => unsubscribe();
  }, []);

  return <div>组件 A</div>;
};

const ComponentB = () => {
  const { refManager } = useContainerContext();

  const handleSelect = (ids: string[]) => {
    // 设置共享状态，会自动通知所有订阅者
    refManager.setSharedState('selectedIds', ids);
  };

  return (
    <button onClick={() => handleSelect(['1', '2', '3'])}>
      选择
    </button>
  );
};

export default () => {
  return (
    <PisellDataSourceContainer dataSource="users">
      <ComponentA />
      <ComponentB />
    </PisellDataSourceContainer>
  );
};
```

## API

### PisellDataSourceContainer Props

| 参数                | 说明           | 类型                                                  | 默认值 | 必填 |
| ------------------- | -------------- | ----------------------------------------------------- | ------ | ---- |
| dataSource          | 数据源配置     | `string \| DataSourceConfig`                          | -      | ✅   |
| autoRun             | 自动执行配置   | `{ list?: boolean }`                                  | -      | ❌   |
| pagination          | 分页配置       | `boolean \| { pageNumber: number; pageSize: number }` | `true` | ❌   |
| extraParams         | 额外请求参数   | `{ list?: Record<string, any> }`                      | -      | ❌   |
| actions             | 操作方法配置   | `ActionsConfig`                                       | -      | ❌   |
| overrideData        | 数据覆盖       | `any`                                                 | -      | ❌   |
| currentValue        | 当前值         | `any`                                                 | -      | ❌   |
| \_\_designMode      | 设计模式       | `boolean`                                             | -      | ❌   |
| childComponentProps | 子组件属性配置 | `ChildComponentPropsType`                             | -      | ❌   |
| children            | 子组件         | `ReactNode`                                           | -      | ✅   |

### ChildComponentPropsType

| 参数                    | 说明                    | 类型                                                                                                                                         |
| ----------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| filterComponent         | Filter 组件属性         | `{ value: { quickFilter?: FilterItemProps[]; otherFilter?: FilterItemProps[] }; formFiltersPrefix?: string; quickFilterMaxLength?: number }` |
| quickFilterComponent    | QuickFilter 组件属性    | `{ filterList: FilterItemProps[]; formFiltersPrefix?: string }`                                                                              |
| filterButtonComponent   | FilterButton 组件属性   | `FilterListProps`                                                                                                                            |
| tabsComponent           | Tabs 组件属性           | `{ items: TabsProps['items']; type?: 'default' \| 'button' \| 'buttonGroup' \| 'dropdown' }`                                                 |
| sortComponent           | Sort 组件属性           | `SortListProps`                                                                                                                              |
| tableComponent          | Table 组件属性          | `AntdTableProps<any>`                                                                                                                        |
| columnsSettingComponent | ColumnsSetting 组件属性 | `{ value?: Record<string, any>[]; onChange?: (val) => void }`                                                                                |
| paginationComponent     | Pagination 组件属性     | `PaginationProps`                                                                                                                            |

### useContainerContext 返回值

| 参数           | 说明               | 类型                                 |
| -------------- | ------------------ | ------------------------------------ |
| serverActions  | 服务端操作方法集合 | `HandleActionContextType`            |
| refManager     | 引用管理器         | `RefManagerContextType`              |
| form           | 表单实例           | `FormInstance`                       |
| onValuesChange | 表单值变化回调     | `(changedValues, allValues) => void` |

### serverActions.list

| 参数         | 说明                     | 类型                                       |
| ------------ | ------------------------ | ------------------------------------------ |
| data         | 列表数据                 | `{ list: any[]; count: number }`           |
| loading      | 加载状态                 | `boolean`                                  |
| error        | 错误信息                 | `Error`                                    |
| run          | 执行查询（原始方法）     | `(params) => void`                         |
| onSearch     | 查询方法（自动处理分页） | `(params?) => void`                        |
| onReset      | 重置方法                 | `() => void`                               |
| onPageChange | 分页切换方法             | `(pageNumber, pageSize) => void`           |
| pagination   | 当前分页状态             | `{ pageNumber: number; pageSize: number }` |

### refManager 方法

| 方法                 | 说明         | 类型                                                           |
| -------------------- | ------------ | -------------------------------------------------------------- |
| registerRef          | 注册组件引用 | `<T>(id: string, ref: T) => void`                              |
| getRef               | 获取组件引用 | `<T>(id: string) => T \| undefined`                            |
| unregisterRef        | 注销组件引用 | `(id: string) => void`                                         |
| getSharedState       | 获取共享状态 | `<T>(key: string) => T \| undefined`                           |
| setSharedState       | 设置共享状态 | `<T>(key: string, value: T) => void`                           |
| subscribeSharedState | 订阅共享状态 | `<T>(key: string, callback: (value: T) => void) => () => void` |

## 内置子组件

PisellDataSourceContainer 提供了一系列开箱即用的子组件：

### PisellDataSourceContainer.Filter

筛选组件，支持快速筛选和高级筛选。

### PisellDataSourceContainer.Table

表格组件，自动连接数据源。

### PisellDataSourceContainer.Pagination

分页组件，自动处理分页逻辑。

### PisellDataSourceContainer.Sort

排序组件。

### PisellDataSourceContainer.ColumnsSetting

列设置组件。

## 高级用法

### 自定义操作

```
const CustomActions = () => {
  const { serverActions, form } = useContainerContext();

  const handleExport = async () => {
    const values = form.getFieldsValue();
    // 导出逻辑
  };

  const handleBatchDelete = async () => {
    const { list } = serverActions;
    // 批量删除逻辑
    await serverActions.destroy.run({ ids: selectedIds });
    list.onSearch(); // 重新查询
  };

  return (
    <div>
      <button onClick={handleExport}>导出</button>
      <button onClick={handleBatchDelete}>批量删除</button>
    </div>
  );
};
```

### 跨组件通信

```
// 组件 A - 设置状态
const ComponentA = () => {
  const { refManager } = useContainerContext();

  const handleClick = () => {
    refManager.setSharedState('currentTab', 'all');
  };

  return <button onClick={handleClick}>切换</button>;
};

// 组件 B - 订阅状态
const ComponentB = () => {
  const { refManager } = useContainerContext();
  const [tab, setTab] = useState('all');

  useEffect(() => {
    return refManager.subscribeSharedState('currentTab', setTab);
  }, []);

  return <div>当前标签：{tab}</div>;
};
```

## 扩展开发

如果你需要开发新的子组件或扩展现有功能，请参考：

- [设计文档](./PisellDataSourceContainer.$tab-design.md)
- [开发文档](./PisellDataSourceContainer.$tab-dev.md)

## 注意事项

1. **数据源配置**: 确保 dataSource 配置正确，可以是字符串（表名）或完整的数据源配置对象
2. **分页配置**: 如果启用分页（pagination=true），onSearch 会自动重置到第一页
3. **表单集成**: 容器内置了 Form 实例，表单值变化会自动触发 onSearch
4. **Ref 管理**: 使用 withContainer HOC 包装组件时，会自动注册和注销 ref
5. **SharedState**: 使用 subscribeSharedState 时，记得在组件卸载时取消订阅
6. **性能优化**: 合理使用 useMemo 和 useCallback 避免不必要的重新渲染

## 最佳实践

1. **统一数据管理**: 将所有数据操作集中在 PisellDataSourceContainer 中管理
2. **组件解耦**: 使用 useContainerContext 访问上下文，保持组件独立性
3. **状态共享**: 使用 SharedState 代替 props drilling
4. **类型安全**: 为 serverActions、refManager 等添加明确的类型定义
5. **错误处理**: 在操作方法中添加错误处理逻辑
6. **加载状态**: 合理使用 loading 状态提升用户体验
