120 lines
3.3 KiB
Markdown
120 lines
3.3 KiB
Markdown
# UTS 模板函数调用错误修复总结
|
||
|
||
## 问题分析
|
||
|
||
在教师仪表板中遇到了模板函数调用错误:
|
||
|
||
### 1. 模板中直接调用导入函数的问题
|
||
```
|
||
error: Expression 'unref(formatDateTime)' of type 'String' cannot be invoked as a function
|
||
error: Function invocation 'formatDateTime(...)' expected
|
||
error: No value passed for parameter 'dateStr'
|
||
```
|
||
|
||
**原因**: UTS 在模板中直接调用导入的函数时存在类型识别问题
|
||
|
||
### 2. 数据类型转换错误
|
||
```
|
||
error: 类型不匹配: 推断类型是UTSJSONObject,但预期的是Activity
|
||
```
|
||
|
||
**原因**: `executeAs` 返回的数据类型与实际使用的类型不匹配
|
||
|
||
### 3. 空数组类型推断问题
|
||
```
|
||
error: Not enough information to infer type variable E
|
||
```
|
||
|
||
**原因**: 错误处理中的空数组无法推断类型
|
||
|
||
## 修复方案
|
||
|
||
### 1. 创建本地包装函数
|
||
```typescript
|
||
// 修复前 - 模板直接调用导入函数
|
||
{{ formatDateTime(activity.created_at) }} // ❌ UTS 模板识别错误
|
||
|
||
// 修复后 - 使用本地包装函数
|
||
const formatDateTimeLocal = (dateStr: string): string => {
|
||
return formatDateTime(dateStr)
|
||
}
|
||
|
||
{{ formatDateTimeLocal(activity.created_at) }} // ✅ 正确调用
|
||
```
|
||
|
||
### 2. 修复数据查询方式
|
||
```typescript
|
||
// 修复前 - 使用 executeAs 但类型不匹配
|
||
.executeAs<AssignmentActivityData>()
|
||
const activities: Array<Activity> = rawData.map(...) // 类型不匹配
|
||
|
||
// 修复后 - 使用 execute() + 类型断言
|
||
.execute()
|
||
const rawData = activitiesResponse.data as Array<AssignmentActivityData>
|
||
const activities: Array<Activity> = rawData.map(...) // 类型匹配
|
||
```
|
||
|
||
### 3. 完善空数组类型
|
||
```typescript
|
||
// 修复前
|
||
data: [] // 类型推断失败
|
||
|
||
// 修复后
|
||
data: [] as Array<GroupMember> // 明确类型
|
||
```
|
||
|
||
## 具体修改
|
||
|
||
### 1. 教师仪表板修复
|
||
```typescript
|
||
// 新增本地包装函数
|
||
const formatDateTimeLocal = (dateStr: string): string => {
|
||
return formatDateTime(dateStr)
|
||
}
|
||
|
||
// 模板调用修复
|
||
<text class="activity-time">{{ formatDateTimeLocal(activity.created_at) }}</text>
|
||
|
||
// 数据查询修复
|
||
.execute()
|
||
const rawData = activitiesResponse.data as Array<AssignmentActivityData>
|
||
```
|
||
|
||
### 2. 消息服务修复
|
||
```typescript
|
||
// 修复空数组类型
|
||
return {
|
||
status: 500,
|
||
data: [] as Array<GroupMember>,
|
||
error: new UniError(...),
|
||
origin: null,
|
||
headers: {}
|
||
} as AkReqResponse<Array<GroupMember>>
|
||
```
|
||
|
||
## UTS 模板函数调用的特点
|
||
|
||
### 1. 导入函数识别问题
|
||
- UTS 模板可能无法正确识别直接导入的函数
|
||
- 需要通过本地包装函数来解决
|
||
- 本地函数调用更稳定可靠
|
||
|
||
### 2. 类型推断限制
|
||
- 模板中的函数调用需要明确的类型信息
|
||
- 避免复杂的类型推断链
|
||
- 使用简单直接的类型断言
|
||
|
||
### 3. 响应式系统兼容
|
||
- 导入的函数可能被误识别为响应式引用
|
||
- 本地包装函数避免了这个问题
|
||
- 确保函数调用的正确性
|
||
|
||
## 最佳实践
|
||
|
||
1. **本地包装函数**: 对于模板中使用的导入函数,创建本地包装
|
||
2. **明确类型转换**: 使用 `execute() + as` 而非 `executeAs()`
|
||
3. **完整错误处理**: 空数组、错误对象都要明确类型
|
||
4. **简化调用链**: 避免模板中的复杂函数调用
|
||
|
||
这次修复解决了 UTS 在模板函数调用方面的限制,确保了应用的正常运行。
|