# ProSelect API

<cite>
**本文引用的文件**
- [packages/core/src/components/ProSelect.vue](file://packages/core/src/components/ProSelect.vue)
- [src/views/ProSelect.vue](file://src/views/ProSelect.vue)
- [packages/libs/request.js](file://packages/libs/request.js)
- [packages/libs/util.js](file://packages/libs/util.js)
- [packages/core/src/ui-adapter/index.ts](file://packages/core/src/ui-adapter/index.ts)
- [packages/components/index.js](file://packages/components/index.js)
- [types/index.d.ts](file://types/index.d.ts)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概览](#架构概览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本文件为 ProSelect 组件的详细 API 参考文档，覆盖属性、事件、插槽与方法，并结合实际源码解析其数据源处理、多选支持与交互行为。ProSelect 基于 UI 适配器动态渲染底层 Select/Option 组件，支持本地列表与远程请求两种数据源模式，具备标题模板化展示与首项自动选择等特性。

## 项目结构
围绕 ProSelect 的关键文件组织如下：
- 组件实现：packages/core/src/components/ProSelect.vue
- 示例演示：src/views/ProSelect.vue
- 请求封装：packages/libs/request.js
- 模板工具：packages/libs/util.js
- UI 适配器入口：packages/core/src/ui-adapter/index.ts
- 组件导出入口：packages/components/index.js
- 类型声明入口：types/index.d.ts

```mermaid
graph TB
A["ProSelect 组件<br/>packages/core/src/components/ProSelect.vue"] --> B["UI 适配器注入<br/>packages/core/src/ui-adapter/index.ts"]
A --> C["请求封装<br/>packages/libs/request.js"]
A --> D["模板工具<br/>packages/libs/util.js"]
E["示例页面<br/>src/views/ProSelect.vue"] --> A
F["组件导出入口<br/>packages/components/index.js"] --> A
G["全局类型入口<br/>types/index.d.ts"] --> A
```

图表来源
- [packages/core/src/components/ProSelect.vue:1-168](file://packages/core/src/components/ProSelect.vue#L1-L168)
- [packages/libs/request.js:1-78](file://packages/libs/request.js#L1-L78)
- [packages/libs/util.js:1-110](file://packages/libs/util.js#L1-L110)
- [packages/core/src/ui-adapter/index.ts:1-7](file://packages/core/src/ui-adapter/index.ts#L1-L7)
- [src/views/ProSelect.vue:1-115](file://src/views/ProSelect.vue#L1-L115)
- [packages/components/index.js:1-23](file://packages/components/index.js#L1-L23)
- [types/index.d.ts:1-19](file://types/index.d.ts#L1-L19)

章节来源
- [packages/core/src/components/ProSelect.vue:1-168](file://packages/core/src/components/ProSelect.vue#L1-L168)
- [src/views/ProSelect.vue:1-115](file://src/views/ProSelect.vue#L1-L115)
- [packages/libs/request.js:1-78](file://packages/libs/request.js#L1-L78)
- [packages/libs/util.js:1-110](file://packages/libs/util.js#L1-L110)
- [packages/core/src/ui-adapter/index.ts:1-7](file://packages/core/src/ui-adapter/index.ts#L1-L7)
- [packages/components/index.js:1-23](file://packages/components/index.js#L1-L23)
- [types/index.d.ts:1-19](file://types/index.d.ts#L1-L19)

## 核心组件
- 组件名称：ProSelect
- 组件职责：基于 UI 适配器渲染下拉选择器，支持本地 list 与远程 request 两种数据源；支持标题模板化展示、首项自动选择、多选模式等。

章节来源
- [packages/core/src/components/ProSelect.vue:7-18](file://packages/core/src/components/ProSelect.vue#L7-L18)

## 架构概览
ProSelect 通过 UI 适配器注入底层 Select/Option 组件，内部维护内部选项列表 innerList，并根据传入的 request 或 list 动态填充。当启用 first 且当前无值时，会自动选择第一条记录并触发变更事件。

```mermaid
sequenceDiagram
participant U as "用户"
participant PS as "ProSelect"
participant UA as "UI 适配器"
participant REQ as "请求封装"
participant TPL as "模板工具"
U->>PS : "挂载组件"
PS->>PS : "init()"
alt "存在 list"
PS->>PS : "innerList = list"
else "存在 request"
PS->>REQ : "customRequest({ request, method })"
REQ-->>PS : "返回响应"
PS->>PS : "innerList = map.dataPath ? get(res, dataPath) : res"
end
opt "first 且 modelValue 为空"
PS->>PS : "取第一条 item"
PS->>UA : "触发 update : modelValue(value)"
PS-->>U : "触发 change(firstItem)"
end
PS->>UA : "渲染 Select/Option支持多选"
U->>PS : "选择/取消选择"
PS->>UA : "更新 v-model 值"
```

图表来源
- [packages/core/src/components/ProSelect.vue:61-95](file://packages/core/src/components/ProSelect.vue#L61-L95)
- [packages/libs/request.js:39-77](file://packages/libs/request.js#L39-L77)
- [packages/libs/util.js:4-19](file://packages/libs/util.js#L4-L19)
- [packages/core/src/ui-adapter/index.ts:1-7](file://packages/core/src/ui-adapter/index.ts#L1-L7)

## 详细组件分析

### 属性（Props）
- request
  - 类型：字符串或对象或函数
  - 作用：远程请求地址或配置；与 list 互斥
  - 默认：无
  - 说明：支持字符串、对象（含 url/request、method、keys 等）、函数形式
  - 参考实现：[packages/core/src/components/ProSelect.vue:27-28](file://packages/core/src/components/ProSelect.vue#L27-L28)，[packages/libs/request.js:39-77](file://packages/libs/request.js#L39-L77)
- method
  - 类型：字符串
  - 作用：HTTP 方法
  - 默认："GET"
  - 参考实现：[packages/core/src/components/ProSelect.vue:29-34](file://packages/core/src/components/ProSelect.vue#L29-L34)
- map
  - 类型：对象
  - 作用：数据路径映射
  - 默认：{ dataPath: "data", titlePath: "title", valuePath: "value" }
  - 子字段：
    - dataPath：响应中数据数组的路径
    - titlePath：选项标题路径或模板表达式
    - valuePath：选项值的路径
  - 参考实现：[packages/core/src/components/ProSelect.vue:36-45](file://packages/core/src/components/ProSelect.vue#L36-L45)，[packages/libs/util.js:4-19](file://packages/libs/util.js#L4-L19)
- first
  - 类型：布尔
  - 作用：是否在无值时自动选择第一条
  - 默认：false
  - 参考实现：[packages/core/src/components/ProSelect.vue:46-51](file://packages/core/src/components/ProSelect.vue#L46-L51)，[packages/core/src/components/ProSelect.vue:89-94](file://packages/core/src/components/ProSelect.vue#L89-L94)
- list
  - 类型：数组
  - 作用：本地选项列表
  - 默认：无
  - 说明：与 request 互斥；优先使用 list
  - 参考实现：[packages/core/src/components/ProSelect.vue:52-54](file://packages/core/src/components/ProSelect.vue#L52-L54)，[packages/core/src/components/ProSelect.vue:74-76](file://packages/core/src/components/ProSelect.vue#L74-L76)
- modelValue
  - 类型：任意
  - 作用：双向绑定的值
  - 默认：无
  - 参考实现：[packages/core/src/components/ProSelect.vue:55](file://packages/core/src/components/ProSelect.vue#L55)
- valueType
  - 类型：字符串
  - 作用：显式指定值类型（如 "string"）
  - 默认：无
  - 参考实现：[packages/core/src/components/ProSelect.vue:56-58](file://packages/core/src/components/ProSelect.vue#L56-L58)，[packages/core/src/components/ProSelect.vue:62-64](file://packages/core/src/components/ProSelect.vue#L62-L64)

章节来源
- [packages/core/src/components/ProSelect.vue:26-59](file://packages/core/src/components/ProSelect.vue#L26-L59)
- [packages/libs/request.js:39-77](file://packages/libs/request.js#L39-L77)
- [packages/libs/util.js:4-19](file://packages/libs/util.js#L4-L19)

### 事件（Events）
- update:modelValue
  - 触发时机：用户选择或清空后，内部值变化时
  - 参数：当前选中的值（单选为标量，多选为数组）
  - 参考实现：[packages/core/src/components/ProSelect.vue:114](file://packages/core/src/components/ProSelect.vue#L114)
- change
  - 触发时机：首项自动选择时，或底层 Select 的 change 事件冒泡
  - 参数：被选中的选项对象（非值，而是完整 item）
  - 参考实现：[packages/core/src/components/ProSelect.vue:93](file://packages/core/src/components/ProSelect.vue#L93)
- 其他底层事件
  - 说明：通过透传 $attrs，可接收底层 Select 的原生事件（如 focus、blur 等），但本仓库未显式声明额外事件回调参数
  - 参考实现：[packages/core/src/components/ProSelect.vue:140](file://packages/core/src/components/ProSelect.vue#L140)

章节来源
- [packages/core/src/components/ProSelect.vue:93](file://packages/core/src/components/ProSelect.vue#L93)
- [packages/core/src/components/ProSelect.vue:114](file://packages/core/src/components/ProSelect.vue#L114)
- [packages/core/src/components/ProSelect.vue:140](file://packages/core/src/components/ProSelect.vue#L140)

### 插槽（Slots）
- 说明：组件未定义具名插槽；图标通过内置 Icon 渲染，标题支持模板表达式
- 参考实现：[packages/core/src/components/ProSelect.vue:133-156](file://packages/core/src/components/ProSelect.vue#L133-L156)

章节来源
- [packages/core/src/components/ProSelect.vue:133-156](file://packages/core/src/components/ProSelect.vue#L133-L156)

### 方法（Methods）
- init()
  - 作用：初始化组件，判定值类型并拉取数据
  - 返回：无
  - 参考实现：[packages/core/src/components/ProSelect.vue:61-64](file://packages/core/src/components/ProSelect.vue#L61-L64)
- getExpText(item)
  - 作用：根据 titlePath 计算显示文本，支持模板表达式
  - 返回：字符串
  - 参考实现：[packages/core/src/components/ProSelect.vue:66-72](file://packages/core/src/components/ProSelect.vue#L66-L72)，[packages/libs/util.js:4-19](file://packages/libs/util.js#L4-L19)
- fetchList()
  - 作用：根据 list 或 request 获取选项列表；必要时设置 first
  - 返回：无
  - 参考实现：[packages/core/src/components/ProSelect.vue:73-95](file://packages/core/src/components/ProSelect.vue#L73-L95)，[packages/libs/request.js:39-77](file://packages/libs/request.js#L39-L77)

章节来源
- [packages/core/src/components/ProSelect.vue:61-95](file://packages/core/src/components/ProSelect.vue#L61-L95)
- [packages/libs/util.js:4-19](file://packages/libs/util.js#L4-L19)
- [packages/libs/request.js:39-77](file://packages/libs/request.js#L39-L77)

### 计算属性与数据流
- innerValue
  - 作用：根据 $attrs.multiple 决定单选或多选模式，统一 v-model 的读写
  - 单选：modelValue
  - 多选：modelValue 为数组；若为字符串则按逗号拆分
  - 参考实现：[packages/core/src/components/ProSelect.vue:101-116](file://packages/core/src/components/ProSelect.vue#L101-L116)
- innerList
  - 作用：内部选项列表
  - 来源：list 或 fetchList 解析后的结果
  - 参考实现：[packages/core/src/components/ProSelect.vue:22](file://packages/core/src/components/ProSelect.vue#L22)，[packages/core/src/components/ProSelect.vue:74-88](file://packages/core/src/components/ProSelect.vue#L74-L88)

章节来源
- [packages/core/src/components/ProSelect.vue:101-116](file://packages/core/src/components/ProSelect.vue#L101-L116)
- [packages/core/src/components/ProSelect.vue:22](file://packages/core/src/components/ProSelect.vue#L22)
- [packages/core/src/components/ProSelect.vue:74-88](file://packages/core/src/components/ProSelect.vue#L74-L88)

### 交互行为与多选支持
- 多选模式
  - 通过 $attrs.multiple 控制底层 Select 的多选能力
  - v-model 在多选时应绑定数组
  - 参考实现：[packages/core/src/components/ProSelect.vue:101-116](file://packages/core/src/components/ProSelect.vue#L101-L116)，[packages/core/src/components/ProSelect.vue:140](file://packages/core/src/components/ProSelect.vue#L140)
- 首项自动选择
  - 当 first 为真且 modelValue 为空时，自动选择第一条并触发 change
  - 参考实现：[packages/core/src/components/ProSelect.vue:89-94](file://packages/core/src/components/ProSelect.vue#L89-L94)
- 清空与重置
  - 通过 clearable 与 v-model 更新可实现清空；示例中通过赋空数组演示
  - 参考实现：[src/views/ProSelect.vue:106-110](file://src/views/ProSelect.vue#L106-L110)

章节来源
- [packages/core/src/components/ProSelect.vue:101-116](file://packages/core/src/components/ProSelect.vue#L101-L116)
- [packages/core/src/components/ProSelect.vue:140](file://packages/core/src/components/ProSelect.vue#L140)
- [src/views/ProSelect.vue:106-110](file://src/views/ProSelect.vue#L106-L110)

### 数据源处理流程
```mermaid
flowchart TD
Start(["进入 fetchList"]) --> HasList{"是否存在 list?"}
HasList --> |是| UseList["innerList = list"]
HasList --> |否| HasReq{"是否存在 request?"}
HasReq --> |否| End(["结束"])
HasReq --> |是| CallReq["customRequest({ request, method })"]
CallReq --> RespOK{"响应存在?"}
RespOK --> |否| End
RespOK --> |是| MapData["根据 dataPath 取数组或直接使用响应"]
MapData --> FirstCheck{"first 且 modelValue 为空?"}
FirstCheck --> |是| AutoSel["取第一条 item 并触发 update:modelValue 与 change"]
FirstCheck --> |否| Done(["完成"])
AutoSel --> Done
```

图表来源
- [packages/core/src/components/ProSelect.vue:73-95](file://packages/core/src/components/ProSelect.vue#L73-L95)
- [packages/libs/request.js:39-77](file://packages/libs/request.js#L39-L77)

## 依赖分析
- 组件依赖
  - UI 适配器：动态注入 Select/Option/Icon
  - 请求封装：统一处理 GET/POST、URL 替换、参数筛选
  - 模板工具：支持 titlePath 中的模板表达式
- 外部依赖
  - lodash-es：数据处理与路径访问
  - axios：HTTP 请求（可通过全局 $http 覆盖）

```mermaid
graph LR
PS["ProSelect"] --> UA["UI 适配器"]
PS --> REQ["请求封装"]
PS --> TPL["模板工具"]
REQ --> AX["axios"]
PS --> LD["lodash-es"]
```

图表来源
- [packages/core/src/components/ProSelect.vue:2-5](file://packages/core/src/components/ProSelect.vue#L2-L5)
- [packages/libs/request.js:1-5](file://packages/libs/request.js#L1-L5)
- [packages/libs/util.js:1-2](file://packages/libs/util.js#L1-L2)

章节来源
- [packages/core/src/components/ProSelect.vue:2-5](file://packages/core/src/components/ProSelect.vue#L2-L5)
- [packages/libs/request.js:1-5](file://packages/libs/request.js#L1-L5)
- [packages/libs/util.js:1-2](file://packages/libs/util.js#L1-L2)

## 性能考虑
- 列表渲染
  - 使用 v-for 渲染 Option，建议控制 innerList 规模，避免超大列表导致卡顿
- 请求缓存
  - 当前未内置缓存策略；对于频繁切换的场景，可在上层自行缓存请求结果
- 模板计算
  - titlePath 支持模板表达式，复杂表达式可能带来额外开销；建议保持简洁
- 监听与刷新
  - request 的深监听会在值变化时重新拉取；频繁变更可能导致多次请求，建议节流或合并

## 故障排查指南
- 无法显示选项
  - 检查 list 或 request 是否正确传入，确认 map.dataPath 与响应结构一致
  - 参考实现：[packages/core/src/components/ProSelect.vue:74-88](file://packages/core/src/components/ProSelect.vue#L74-L88)
- 选中值类型不符
  - 多选需绑定数组；可通过 valueType 或显式设置 v-model 类型
  - 参考实现：[packages/core/src/components/ProSelect.vue:101-116](file://packages/core/src/components/ProSelect.vue#L101-L116)
- 首项未自动选择
  - 确认 first 为 true 且 modelValue 为空；检查第一条数据的 valuePath
  - 参考实现：[packages/core/src/components/ProSelect.vue:89-94](file://packages/core/src/components/ProSelect.vue#L89-L94)
- 标题显示异常
  - 检查 titlePath 是否为有效路径或合法模板表达式
  - 参考实现：[packages/libs/util.js:4-19](file://packages/libs/util.js#L4-L19)
- 请求失败或跨域
  - 检查请求地址、headers、token 注入逻辑
  - 参考实现：[packages/libs/request.js:32-38](file://packages/libs/request.js#L32-L38)，[packages/libs/request.js:44-51](file://packages/libs/request.js#L44-L51)

章节来源
- [packages/core/src/components/ProSelect.vue:74-94](file://packages/core/src/components/ProSelect.vue#L74-L94)
- [packages/libs/util.js:4-19](file://packages/libs/util.js#L4-L19)
- [packages/libs/request.js:32-51](file://packages/libs/request.js#L32-L51)

## 结论
ProSelect 提供了灵活的数据源配置、标题模板化展示与首项自动选择能力，同时通过 UI 适配器实现与底层 Select/Option 的解耦。在多选场景下，需确保 v-model 为数组；在远程数据场景下，合理配置 map 与请求参数可获得最佳体验。

## 附录

### 完整属性清单
- request：远程请求配置
- method：HTTP 方法
- map：{ dataPath, titlePath, valuePath }
- first：是否自动选中首项
- list：本地选项数组
- modelValue：双向绑定值
- valueType：值类型提示

章节来源
- [packages/core/src/components/ProSelect.vue:26-59](file://packages/core/src/components/ProSelect.vue#L26-L59)

### 事件与参数
- update:modelValue：当前选中值（单选标量/多选数组）
- change：被选中的完整选项对象

章节来源
- [packages/core/src/components/ProSelect.vue:93](file://packages/core/src/components/ProSelect.vue#L93)
- [packages/core/src/components/ProSelect.vue:114](file://packages/core/src/components/ProSelect.vue#L114)

### 插槽
- 无具名插槽；图标与标题通过内置组件与模板表达式渲染

章节来源
- [packages/core/src/components/ProSelect.vue:133-156](file://packages/core/src/components/ProSelect.vue#L133-L156)

### 方法调用示例与返回值
- init()
  - 用途：初始化并拉取数据
  - 返回：无
  - 参考实现：[packages/core/src/components/ProSelect.vue:61-64](file://packages/core/src/components/ProSelect.vue#L61-L64)
- getExpText(item)
  - 用途：计算标题文本（支持模板）
  - 返回：字符串
  - 参考实现：[packages/core/src/components/ProSelect.vue:66-72](file://packages/core/src/components/ProSelect.vue#L66-L72)，[packages/libs/util.js:4-19](file://packages/libs/util.js#L4-L19)
- fetchList()
  - 用途：根据 list 或 request 获取选项列表
  - 返回：无
  - 参考实现：[packages/core/src/components/ProSelect.vue:73-95](file://packages/core/src/components/ProSelect.vue#L73-L95)，[packages/libs/request.js:39-77](file://packages/libs/request.js#L39-L77)

### 示例页面参考
- 多选与首项自动选择示例
  - 参考实现：[src/views/ProSelect.vue:45-102](file://src/views/ProSelect.vue#L45-L102)
- 清空与重置示例
  - 参考实现：[src/views/ProSelect.vue:106-110](file://src/views/ProSelect.vue#L106-L110)