Files
akmon/doc_zhipao/VUE3_SETUP_CONVERSION_GUIDE.md
2026-01-20 08:04:15 +08:00

229 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Vue 3 Setup 模式转换说明
## 概述
已成功将 `pages/sport/teacher/records.uvue` 从 Vue 2 Options API 转换为 Vue 3 Composition API (setup模式)。
## 主要变化
### 1. 脚本标签更改
```vue
<!-- 旧版本 -->
<script lang="uts">
export default {
// Options API
}
</script>
<!-- 新版本 -->
<script setup lang="uts">
// Composition API
</script>
```
### 2. 导入语句
```typescript
// 新增 Vue 3 组合式 API 导入
import { ref, computed, onMounted, nextTick } from 'vue'
```
### 3. 数据定义转换
#### 旧版本 (Options API)
```typescript
data() {
return {
recordsRef: null,
error: null,
recordsLoading: false,
allRecords: [],
// ...其他状态
}
}
```
#### 新版本 (Composition API)
```typescript
// 使用 ref 定义响应式数据
const recordsRef = ref<SupadbComponentPublicInstance | null>(null)
const error = ref<string | null>(null)
const recordsLoading = ref(false)
const allRecords = ref<UTSJSONObject[]>([])
// ...其他状态
```
### 4. 计算属性转换
#### 旧版本
```typescript
computed: {
recordsFilter() {
const filter = {}
if (this.activeStatusFilter !== 'all') {
filter.status = this.activeStatusFilter
}
return filter
}
}
```
#### 新版本
```typescript
const recordsFilter = computed(() => {
const filter: any = {}
if (activeStatusFilter.value !== 'all') {
filter.status = activeStatusFilter.value
}
return filter
})
```
### 5. 方法定义转换
#### 旧版本
```typescript
methods: {
initializeDates() {
const now = new Date()
this.endDate = now.toISOString().split('T')[0]
}
}
```
#### 新版本
```typescript
const initializeDates = () => {
const now = new Date()
endDate.value = now.toISOString().split('T')[0]
}
```
### 6. 生命周期钩子转换
#### 旧版本
```typescript
onLoad() {
this.initializeDates()
},
onReady() {
this.recordsRef = this.$refs["recordsRef"]
}
```
#### 新版本
```typescript
onMounted(() => {
initializeDates()
nextTick(() => {
recordsRef.value = uni.createSelectorQuery().select('#recordsRef')
})
})
```
## 关键技术点
### 1. 响应式引用 (ref)
- 基本数据类型使用 `ref()`
- 对象和数组也使用 `ref()`
- 访问值时需要 `.value`
### 2. 计算属性 (computed)
- 使用 `computed()` 函数包装
- 依赖的响应式数据自动追踪
- 返回只读的响应式引用
### 3. 模板引用
- 使用 `ref` 属性绑定到响应式引用
- 通过 `.value` 访问 DOM 元素或组件实例
### 4. 事件处理
- 方法定义为普通函数
- 自动暴露给模板使用
### 5. 类型安全
- 使用 TypeScript 泛型增强类型安全
- 明确定义参数和返回值类型
## 优势
### 1. 更好的类型推导
```typescript
// 类型自动推导
const count = ref(0) // Ref<number>
const user = ref<User | null>(null) // Ref<User | null>
```
### 2. 更好的代码组织
- 相关逻辑可以组织在一起
- 更容易提取和复用逻辑
### 3. 更好的树摇优化
- 只导入使用的功能
- 打包体积更小
### 4. 更好的 IDE 支持
- 更准确的类型检查
- 更好的自动补全
## 注意事项
### 1. 响应式访问
```typescript
// ❌ 错误:直接访问
console.log(count)
// ✅ 正确:通过 .value 访问
console.log(count.value)
```
### 2. 模板中自动解包
```vue
<!-- 模板中自动解包无需 .value -->
<text>{{ count }}</text>
<input v-model="searchQuery" />
```
### 3. 解构赋值
```typescript
// ❌ 错误:会失去响应性
const { count, name } = reactive({ count: 0, name: 'test' })
// ✅ 正确:使用 toRefs
const { count, name } = toRefs(reactive({ count: 0, name: 'test' }))
```
## 性能优化
### 1. 懒加载计算属性
```typescript
const expensiveComputed = computed(() => {
// 只在依赖变化时重新计算
return heavyCalculation(someReactiveData.value)
})
```
### 2. 条件性响应式
```typescript
const conditionalData = ref(null)
// 只在需要时创建响应式数据
```
## 迁移清单
- ✅ 数据属性转换为 ref/reactive
- ✅ 计算属性转换为 computed
- ✅ 方法定义更新
- ✅ 生命周期钩子更新
- ✅ 模板引用更新
- ✅ 类型定义完善
- ✅ 错误处理优化
## 后续优化建议
1. **逻辑提取**: 将相关逻辑提取到组合式函数中
2. **性能优化**: 使用 `shallowRef` 优化大型数据结构
3. **类型优化**: 进一步完善 TypeScript 类型定义
4. **测试覆盖**: 添加单元测试确保功能正确性
转换后的代码更符合 Vue 3 最佳实践,具有更好的类型安全性和代码可维护性。