Vue 组件设计,10 个实用技巧

38 阅读1分钟

1. 利用 TypeScript 定义 Props

保证类型安全,自动补全,自文档化。

<script setup lang="ts">
interface UserProfileProps {
  userProfile: User
  showAvatar?: boolean
  avatarSize?: 'small' | 'medium' | 'large'
}

const props = withDefaults(defineProps<UserProfileProps>(), {
  showAvatar: true,
  avatarSize: 'medium'
})
</script>

2. 为 Emits 添加类型

事件载荷类型安全,开发更直观。

<script setup lang="ts">
const emit = defineEmits<{
  'update:selected': [id: number]
  'profile-view': [user: User]
}>()

function selectUser(user: User) {
  emit('update:selected', user.id)
  emit('profile-view', user)
}
</script>

3. 使用 Composables 复用逻辑

提取复杂逻辑,复用更方便。

<script setup lang="ts">
import { useUserStatus } from '@/composables/useUserStatus'

const props = defineProps<{ user: User }>()
const { isOnline, statusText } = useUserStatus(props.user)
</script>

4. 保持组件小巧单一职责

大组件拆分,小组件聚合。

<template>
  <UserHeader :user="user" />
  <UserStats :statistics="userStats" />
  <RecentActivity :activities="recentActivities" />
</template>

5. 使用接口定义组件状态

组件状态结构清晰,避免低级错误。

interface TaskItem {
  id: number
  title: string
  completed: boolean
  dueDate?: Date
  priority: 'low' | 'medium' | 'high'
}

const tasks = ref<TaskItem[]>([])

6. 用 Computed 处理派生数据

代替模板逻辑,更可读。

<script setup>
const fullName = computed(()=> `${user.value.firstName} ${user.value.lastName}`)
</script>

<template>
  <div>{{ fullName }}</div>
</template>

7. 处理异步的错误与加载状态

保证用户体验完整。

<template>
  <LoadingSpinner v-if="loading" />
  <ErrorMessage v-else-if="error" :message="error.message" @retry="fetchUserData"/>
  <UserProfile v-else-if="user" :user="user"/>
  <EmptyState v-else message="无数据"/>
</template>

8. 使用类型化插槽 (Typed Slots)

灵活又安全。

<slot :name="`cell-${String(column.key)}`" :item="item" :value="item[column.key]">
  {{ item[column.key] }}
</slot>

9. 用 CSS 变量实现主题化

样式灵活可配置。

.button {
  --button-bg: var(--primary-color, #3490dc);
  background-color: var(--button-bg);
}

10. 用 TS + JSDoc 自文档化

IDE 自动提示 + 维护更轻松。

/**
 * 用户信息卡片
 * @example
 * <UserProfileCard :user="user" @profile-click="handler"/>
 */
export interface User {
  id: number
  name: string
  avatarUrl?: string
}

📌 这 10 个技巧涵盖了 类型安全、逻辑复用、组件拆分、状态管理、UI 灵活性、文档化 等关键点。