# 数据存储取数模块

selectors 是 AiPMChat 数据流研发框架下的取数模块，它的作用是从 store 中以特定特务逻辑取出数据，供组件消费使用。

以 `src/store/tool/slices/plugin/selectors.ts` 为例：

这个 TypeScript 代码段定义了一个名为 `pluginSelectors` 的对象，该对象包含一系列用于从插件存储状态中检索数据的选择器函数。选择器是一种从 zustand 中提取和派生数据的函数。这个特定的例子是为了管理与前端应用程序的插件系统相关的状态。

下面是一些关键点的说明：

- `getCustomPluginById`: 根据插件 ID 返回自定义插件信息。
- `getInstalledPluginById`: 根据插件 ID 返回已安装插件的信息。
- `getPluginManifestById`: 根据插件 ID 返回插件清单。
- `getPluginMetaById`: 根据插件 ID 返回插件元数据。
- `getPluginSettingsById`: 根据插件 ID 返回插件设置。
- `installedCustomPluginMetaList`: 返回所有已安装的自定义插件的元数据列表。
- `installedPluginManifestList`: 返回所有已安装插件的清单列表。
- `installedPluginMetaList`: 返回所有已安装插件的元数据列表。
- `installedPlugins`: 返回所有已安装插件的列表。
- `isPluginHasUI`: 根据插件 ID 确定插件是否有 UI 组件。
- `isPluginInstalled`: 根据插件 ID 检查插件是否已安装。
- `storeAndInstallPluginsIdList`: 返回 store 中和已安装插件的所有 ID 列表。

选择器通过将复杂的状态选择逻辑封装在单独的函数中，使得在应用程序的其他部分调用状态数据时，代码更加简洁和直观。此外，由于使用了 TypeScript，每个函数都可以具有明确的输入和输出类型，这有助于提高代码的可靠性和开发效率。

在组件中，只需引入相应的选择器即可直接获取最终消费的数据：

```tsx | pure
import { useToolStore } from '@/store/tool';
import { pluginSelectors } from '@/store/tool/selectors';

const Render = () => {
  const list = useToolStore(pluginSelectors.installedPluginMetaList);

  return <> ... </>;
};
```

这样实现的好处在于：

1. **解耦和重用**：通过将选择器独立于组件，我们可以在多个组件之间复用这些选择器而不需要重写取数逻辑。这减少了重复代码，提高了开发效率，并且使得代码库更加干净和易于维护。
2. **性能优化**：选择器可以用来计算派生数据，这样可以避免在每个组件中重复计算相同的数据。当状态发生变化时，只有依赖于这部分状态的选择器才会重新计算，从而减少不必要的渲染和计算。
3. **易于测试**：选择器是纯函数，它们仅依赖于传入的参数。这意味着它们可以在隔离的环境中进行测试，无需模拟整个 store 或组件树。
4. **类型安全**：由于 AiPMChat 使用 TypeScript，每个选择器都有明确的输入和输出类型定义。这为开发者提供了自动完成和编译时检查的优势，减少了运行时错误。
5. **可维护性**：选择器集中了状态的读取逻辑，使得跟踪状态的变化和管理更加直观。如果状态结构发生变化，我们只需要更新相应的选择器，而不是搜索和替换整个代码库中的多个位置。
6. **可组合性**：选择器可以组合其他选择器，以创建更复杂的选择逻辑。这种模式允许开发者构建一个选择器层次结构，使得状态选择更加灵活和强大。
7. **简化组件逻辑**：组件不需要知道状态的结构或如何获取和计算需要的数据。组件只需调用选择器即可获取渲染所需的数据，这使得组件逻辑变得更简单和清晰。

通过这样的设计，AiPMChat 的开发者可以更专注于构建用户界面和业务逻辑，而不必担心数据的获取和处理细节。这种模式也为未来可能的状态结构变更提供了更好的适应性和扩展性。
