Vue3 组件结构规范
1. 组件文件结构
基本结构
vue
<template>
<!-- 模板内容 -->
</template>
<script setup lang="ts">
// 导入语句
import { ref, computed } from 'vue'
import type { PropType } from 'vue'
// 类型定义
interface Props {
title: string
count?: number
}
// Props 定义
const props = defineProps<Props>()
// Emits 定义
const emit = defineEmits<{
(e: 'update', value: number): void
(e: 'delete'): void
}>()
// 响应式数据
const count = ref(0)
const state = reactive({
loading: false,
error: null
})
// 计算属性
const doubleCount = computed(() => count.value * 2)
// 方法
const increment = () => {
count.value++
emit('update', count.value)
}
// 生命周期钩子
onMounted(() => {
// 初始化逻辑
})
onUnmounted(() => {
// 清理逻辑
})
</script>
<style scoped lang="scss">
// 样式定义
</style>
2. 组件目录结构
功能组件目录
FeatureComponent/
├── index.vue # 组件入口文件
├── components/ # 子组件
│ ├── SubComponent.vue
│ └── AnotherComponent.vue
├── composables/ # 组合式函数
│ ├── useFeature.ts
│ └── useAnotherFeature.ts
├── types.ts # 类型定义
└── constants.ts # 常量定义
3. 组件设计原则
单一职责
vue
<!-- 好的例子 -->
<template>
<div class="user-card">
<UserAvatar :user="user" />
<UserInfo :user="user" />
<UserActions :user="user" @action="handleAction" />
</div>
</template>
组件通信
vue
<!-- 父组件 -->
<template>
<UserProfile
:user="user"
@update="handleUpdate"
@delete="handleDelete"
/>
</template>
<!-- 子组件 -->
<script setup lang="ts">
const props = defineProps<{
user: User
}>()
const emit = defineEmits<{
(e: 'update', user: User): void
(e: 'delete'): void
}>()
</script>
4. 组合式函数
基本结构
typescript
// composables/useCounter.ts
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
function decrement() {
count.value--
}
return {
count,
doubleCount,
increment,
decrement
}
}
使用示例
vue
<script setup lang="ts">
import { useCounter } from '@/composables/useCounter'
const { count, doubleCount, increment, decrement } = useCounter(0)
</script>
5. 类型定义
组件 Props 类型
typescript
// types.ts
export interface User {
id: number
name: string
email: string
role: 'admin' | 'user'
}
export interface UserCardProps {
user: User
showActions?: boolean
onAction?: (action: string) => void
}
事件类型
typescript
// types.ts
export type UserEvents = {
(e: 'update', user: User): void
(e: 'delete', userId: number): void
(e: 'select', user: User): void
}
6. 样式规范
Scoped 样式
vue
<style scoped lang="scss">
.user-card {
&__header {
// 样式定义
}
&__body {
// 样式定义
}
&__footer {
// 样式定义
}
}
</style>
CSS 变量
vue
<style scoped lang="scss">
:root {
--primary-color: #42b983;
--secondary-color: #2c3e50;
--spacing-unit: 8px;
}
.component {
color: var(--primary-color);
padding: var(--spacing-unit);
}
</style>
7. 最佳实践
1. 组件命名
- 使用 PascalCase
- 使用有意义的名称
- 避免使用缩写
2. Props 定义
- 使用 TypeScript 类型
- 提供默认值
- 使用 required 标记必需属性
3. 事件处理
- 使用 kebab-case 命名事件
- 提供事件参数类型
- 使用 emit 函数发送事件
4. 响应式数据
- 使用 ref 和 reactive
- 避免过度使用响应式
- 合理使用计算属性
5. 生命周期
- 使用 onMounted 和 onUnmounted
- 在 onUnmounted 中清理资源
- 避免在 setup 中直接使用生命周期
6. 样式组织
- 使用 scoped 样式
- 使用 BEM 命名规范
- 使用 CSS 变量
- 避免使用 !important
7. 代码组织
- 保持导入顺序一致
- 相关逻辑放在一起
- 使用注释说明复杂逻辑
8. 性能优化
- 使用 v-memo
- 合理使用 v-show 和 v-if
- 避免不必要的计算
- 使用 shallowRef 和 shallowReactive
9. 测试
- 编写单元测试
- 测试组件行为
- 测试事件处理
- 测试异步操作
10. 文档
- 提供组件说明
- 说明 Props 和事件
- 提供使用示例
- 说明注意事项