# 表达式渲染

<cite>
**本文引用的文件**
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/core/src/components/ProTypeItem/ProTypeItem.vue](file://packages/core/src/components/ProTypeItem/ProTypeItem.vue)
- [packages/libs/util.js](file://packages/libs/util.js)
- [packages/components/ProTypeItem/comFillArr.js](file://packages/components/ProTypeItem/comFillArr.js)
- [packages/components/ProTable.vue](file://packages/components/ProTable.vue)
- [packages/components/ProForm.vue](file://packages/components/ProForm.vue)
- [packages/components/ProSearch.vue](file://packages/components/ProSearch.vue)
- [src/views/Home.vue](file://src/views/Home.vue)
</cite>

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

## 简介
本篇文档聚焦于 ProTypeItem 的“表达式渲染”能力，系统阐述以下主题：
- useExp 属性的作用与触发机制
- evalUse 方法的实现原理与运行时行为
- text 属性中表达式的语法与参数绑定（value）
- 动态样式与内容渲染的应用场景（动态样式、条件显示、内容格式化等）
- 性能优化建议与常见错误处理方法
- 结合真实示例路径，帮助读者快速上手与排错

## 项目结构
ProTypeItem 作为 ProForm、ProSearch、ProTable 等组件的通用渲染器，负责根据配置对象动态生成输入控件或展示元素，并在需要时对样式与文本进行表达式求值。

```mermaid
graph TB
subgraph "表单与表格层"
ProForm["ProForm.vue"]
ProSearch["ProSearch.vue"]
ProTable["ProTable.vue"]
end
subgraph "类型项渲染层"
ProTypeItem["ProTypeItem.vue<br/>useExp/evalUse/text/style"]
ComFillArr["comFillArr.js<br/>占满宽度组件清单"]
end
subgraph "工具层"
Util["util.js<br/>commonToFn/template/JSON解析"]
end
ProForm --> ProTypeItem
ProSearch --> ProTypeItem
ProTable --> ProTypeItem
ProTypeItem --> Util
ProTypeItem --> ComFillArr
```

图示来源
- [packages/components/ProForm.vue](file://packages/components/ProForm.vue)
- [packages/components/ProSearch.vue](file://packages/components/ProSearch.vue)
- [packages/components/ProTable.vue](file://packages/components/ProTable.vue)
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/components/ProTypeItem/comFillArr.js](file://packages/components/ProTypeItem/comFillArr.js)
- [packages/libs/util.js](file://packages/libs/util.js)

章节来源
- [packages/components/ProForm.vue](file://packages/components/ProForm.vue)
- [packages/components/ProSearch.vue](file://packages/components/ProSearch.vue)
- [packages/components/ProTable.vue](file://packages/components/ProTable.vue)
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/components/ProTypeItem/comFillArr.js](file://packages/components/ProTypeItem/comFillArr.js)
- [packages/libs/util.js](file://packages/libs/util.js)

## 核心组件
- ProTypeItem：负责根据 renderItem 配置渲染组件，支持 useExp 开启表达式渲染，支持 evalUse 对 style 进行动态求值，支持在文本插槽中使用表达式（value 为当前模型值）。
- util.js：提供通用函数转换（commonToFn），用于将字符串或函数形式的格式化器转换为可执行函数；同时提供模板字符串解析工具（template）。
- comFillArr.js：声明哪些组件默认占满容器宽度，影响渲染时的类名与布局。

章节来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/libs/util.js](file://packages/libs/util.js)
- [packages/components/ProTypeItem/comFillArr.js](file://packages/components/ProTypeItem/comFillArr.js)

## 架构总览
ProTypeItem 在渲染阶段根据 renderItem 的字段决定行为：
- useExp 为真时，对 style 和 text 分别进行表达式求值
- style 使用 evalUse 将每个样式键值对作为函数执行，传入当前模型值
- text 使用 new Function("value", "return " + text)(value) 执行表达式，得到最终文本
- 若 renderItem 为函数，则直接调用该函数并注入上下文（含 v-model 绑定）

```mermaid
sequenceDiagram
participant Parent as "父组件(ProForm/ProSearch/ProTable)"
participant PTI as "ProTypeItem"
participant Util as "util.js(commonToFn)"
participant VM as "Vue渲染"
Parent->>PTI : 传入 renderItem/useExp/modelValue
PTI->>PTI : 判断 useExp 与 style 存在
PTI->>PTI : evalUse(style, modelValue)
PTI->>VM : 渲染组件(含动态style)
PTI->>PTI : 判断 useExp 与 text
PTI->>PTI : 执行表达式(text)
PTI->>Util : format/formatWapper(如存在)
PTI-->>Parent : 触发 update : modelValue/wapperInput
```

图示来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/libs/util.js](file://packages/libs/util.js)

## 详细组件分析

### ProTypeItem 表达式渲染机制
- useExp：布尔开关，开启后对 style 与 text 启用表达式求值
- evalUse(obj, innerValue)：遍历样式对象，对每个值为字符串的项构造函数并执行，将 innerValue 作为 value 传入，返回新的样式对象
- text 表达式：当 useExp 为真时，将 text 作为函数体执行，value 即为当前模型值 modelValue
- 输入处理 input(value)：若 renderItem 中存在 format/formatWapper，则通过 commonToFn 转换并发出更新事件

```mermaid
flowchart TD
Start(["进入 render"]) --> CheckRI["检查 renderItem 是否为对象"]
CheckRI --> |是| ReadFields["读取 useExp/text/type/style/props/on/scopedSlots"]
CheckRI --> |否| FnRender["调用 renderItem 函数渲染"]
ReadFields --> StyleEval{"useExp 且 style 存在？"}
StyleEval --> |是| EvalUse["evalUse(style, modelValue)"]
StyleEval --> |否| KeepStyle["保持原 style"]
EvalUse --> MergeStyle["合并到组件 style"]
KeepStyle --> MergeStyle
MergeStyle --> TextEval{"useExp 且 text 存在？"}
TextEval --> |是| ExecText["执行表达式(text,value=modelValue)"]
TextEval --> |否| KeepText["保持原 text"]
ExecText --> RenderComp["渲染组件(含动态style与动态text)"]
KeepText --> RenderComp
FnRender --> EmitBind["确保 v-model 绑定并返回"]
RenderComp --> End(["完成"])
EmitBind --> End
```

图示来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)

章节来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)

### evalUse 实现原理
- 输入：样式对象与当前模型值
- 处理：对每个值为字符串的样式项，使用 new Function("value", "return " + val)(innerValue) 动态执行，得到最终样式值
- 输出：新的样式对象，供组件渲染使用

```mermaid
flowchart TD
A["输入: {key: expr} 与 value"] --> B["遍历键值对"]
B --> C{"val 是否为字符串？"}
C --> |是| D["new Function('value','return '+val)(value)"]
C --> |否| E["保持原值"]
D --> F["写入新对象"]
E --> F
F --> G["返回新样式对象"]
```

图示来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)

章节来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)

### text 表达式与 value 参数
- 当 useExp 为真时，text 字段会被当作函数体执行，其中 value 为当前模型值
- 常见用法：条件显示、颜色切换、文案拼接、格式化输出等
- 示例参考（路径）：
  - [src/views/Home.vue](file://src/views/Home.vue) 中的 renderTable 示例展示了 useExp 与 text、style 的组合使用

章节来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [src/views/Home.vue](file://src/views/Home.vue)

### 输入格式化与包装
- 若 renderItem 定义了 format 或 formatWapper，input 方法会通过 commonToFn 将输入值转换为期望格式
- formatWapper：返回一个包含键值的对象，父组件通过 wapperInput 合并到表单值中
- 普通 format：直接返回转换后的值，通过 update:modelValue 更新

章节来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/libs/util.js](file://packages/libs/util.js)

### 与上层组件的集成
- ProForm/ProSearch/ProTable 通过 v-model 与 ProTypeItem 交互，传递 item/renderItem/modelValue/outData 等上下文
- ProTypeItem 内部确保渲染出的组件具备 modelValue 与 onUpdate:modelValue，保证双向绑定生效

```mermaid
sequenceDiagram
participant FT as "ProForm/ProSearch/ProTable"
participant PTI as "ProTypeItem"
participant Comp as "具体组件(i-input等)"
participant Util as "util.js"
FT->>PTI : v-model 绑定 modelValue
FT->>PTI : 传入 renderItem/useExp
PTI->>PTI : 渲染 Comp 并注入 modelValue/onUpdate : modelValue
Comp-->>PTI : 用户输入触发 onUpdate : modelValue
PTI->>Util : format/formatWapper(如有)
PTI-->>FT : update : modelValue 或 wapperInput
```

图示来源
- [packages/components/ProForm.vue](file://packages/components/ProForm.vue)
- [packages/components/ProSearch.vue](file://packages/components/ProSearch.vue)
- [packages/components/ProTable.vue](file://packages/components/ProTable.vue)
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/libs/util.js](file://packages/libs/util.js)

## 依赖分析
- ProTypeItem 依赖：
  - lodash-es：用于对象/数组遍历与判空
  - util.js：通用函数转换与模板解析
  - comFillArr.js：组件宽度策略
  - Vue：h/resolveComponent/v-model 语义
- 上层组件（ProForm/ProSearch/ProTable）依赖 ProTypeItem 进行统一渲染

```mermaid
graph LR
Lodash["lodash-es"] --> PTI["ProTypeItem"]
Util["util.js"] --> PTI
Fill["comFillArr.js"] --> PTI
Vue["Vue(h/resolveComponent)"] --> PTI
PTI --> ProForm["ProForm"]
PTI --> ProSearch["ProSearch"]
PTI --> ProTable["ProTable"]
```

图示来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/libs/util.js](file://packages/libs/util.js)
- [packages/components/ProTypeItem/comFillArr.js](file://packages/components/ProTypeItem/comFillArr.js)
- [packages/components/ProForm.vue](file://packages/components/ProForm.vue)
- [packages/components/ProSearch.vue](file://packages/components/ProSearch.vue)
- [packages/components/ProTable.vue](file://packages/components/ProTable.vue)

章节来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/libs/util.js](file://packages/libs/util.js)
- [packages/components/ProTypeItem/comFillArr.js](file://packages/components/ProTypeItem/comFillArr.js)
- [packages/components/ProForm.vue](file://packages/components/ProForm.vue)
- [packages/components/ProSearch.vue](file://packages/components/ProSearch.vue)
- [packages/components/ProTable.vue](file://packages/components/ProTable.vue)

## 性能考虑
- 避免在 style 表达式中进行重型计算，尽量只做简单逻辑（三元、常量替换等）
- 将复杂逻辑抽离到 format 或外部函数，减少每次渲染的函数构造与执行成本
- 控制表达式长度与嵌套层级，避免长字符串频繁拼接
- 对高频更新的字段，优先使用静态样式或缓存中间结果
- 使用 scopedSlots 时注意仅在必要时动态计算，避免不必要的 h 调用

## 故障排查指南
- 表达式报错
  - 症状：控制台出现语法错误或运行时异常
  - 排查：确认表达式语法正确，value 变量可用；避免访问不存在的属性
  - 参考实现位置：[packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- 样式未生效
  - 症状：useExp 开启但样式未变化
  - 排查：确认 style 为对象且值为字符串表达式；确认 evalUse 返回的样式对象被合并到组件
  - 参考实现位置：[packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- 文本未动态更新
  - 症状：useExp 开启但 text 未随值变化
  - 排查：确认 text 为字符串表达式；确认 modelValue 变更触发重新渲染
  - 参考实现位置：[packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- 输入格式化无效
  - 症状：format/formatWapper 未生效
  - 排查：确认 renderItem 中 format 类型与返回值；formatWapper 应返回对象以便合并
  - 参考实现位置：[packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)，[packages/libs/util.js](file://packages/libs/util.js)

章节来源
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/libs/util.js](file://packages/libs/util.js)

## 结论
ProTypeItem 的表达式渲染通过 useExp、evalUse 与 text 表达式，实现了对样式与内容的动态控制。结合 format/formatWapper，可在输入阶段完成数据格式化与包装。合理使用表达式与格式化器，可显著提升表单/表格的灵活性与可维护性。建议在复杂场景下将逻辑外置，避免在渲染路径中执行重型计算，以保障性能与稳定性。

## 附录：表达式语法与示例
- 基本语法
  - useExp：布尔开关，开启后对 style 与 text 生效
  - text：字符串表达式，value 为当前模型值
  - style：对象，值为字符串表达式，通过 evalUse 计算
- 常见应用场景
  - 动态样式：根据数值范围切换颜色或尺寸
  - 条件显示：根据状态显示不同文案或图标
  - 内容格式化：将时间戳格式化为日期字符串
- 示例参考（路径）
  - [src/views/Home.vue](file://src/views/Home.vue) 中的 renderTable 示例展示了 useExp、text、style 的组合使用
  - [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue) 展示了 evalUse 与表达式执行的实现位置

章节来源
- [src/views/Home.vue](file://src/views/Home.vue)
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)