编辑 | blame | 历史 | 原始文档

---
name: vue-component-patterns
description: Vue 3 组件开发模式,包括 Composition API、Props/Emits 定义、组件命名规范。适用于开发 Vue 组件时。

origin: ECC

Vue 3 组件开发模式

基于 Vue Vben Admin 项目的 Vue 3 组件开发规范。

When to Use

  • 开发新的 Vue 组件
  • 定义组件 Props 和 Emits
  • 使用 Composition API
  • 组件状态管理和生命周期

How It Works

项目使用 Vue 3.5 + TypeScript + <script setup> 语法。

组件定义规范

基础结构

<script lang="ts" setup>
import type { PropsType } from './types';

import { ref, computed } from 'vue';

// 1. 组件命名(必须)
defineOptions({ name: 'ComponentName' });

// 2. Props 定义
interface Props {
  userId: number;
  userName?: string;
}

const props = withDefaults(defineProps<Props>(), {
  userName: '',
});

// 3. Emits 定义
interface Emits {
  (e: 'update', value: string): void;
  (e: 'delete', id: number): void;
}

const emit = defineEmits<Emits>();

// 4. 响应式状态
const loading = ref(false);

// 5. 计算属性
const displayName = computed(() => props.userName || '未命名');

// 6. 方法
function handleSubmit() {
  emit('update', displayName.value);
}
</script>

<template>
  <div class="component-name">
    <!-- 模板内容 -->
  </div>
</template>

<style lang="scss" scoped>
.component-name {
  /* 样式 */
}
</style>

TypeScript 规范

// ✅ 正确:使用 import type 导入类型
import type { UserInfo } from '#/api/system/user';

// ✅ 正确:定义具体接口
interface Props {
  userId: number;
  userName?: string;
}

// ❌ 错误:使用 any
const data: any = {};

// ✅ 正确:使用 unknown + 类型守卫
function getErrorMessage(error: unknown): string {
  if (error instanceof Error) {
    return error.message;
  }
  return '未知错误';
}

页面文件结构

标准 CRUD 页面的文件结构:

views/
└── system/
    └── user/
        ├── index.vue        # 列表页
        ├── data.ts          # 数据定义(表格列、表单 Schema)
        └── modules/
            ├── form.vue     # 表单弹窗
            └── detail.vue   # 详情弹窗(可选)

导入路径层级

文件位置 导入层级
index.vue 4 层 ../..
modules/form.vue 5 层 ../../..
// index.vue 中的导入
import { useFormSchema } from '../data';

// modules/form.vue 中的导入
import { useFormSchema } from '../../data';

组件命名规范

类型 命名规则 示例
页面组件 与目录名一致 UserList.vue
业务组件 功能名 + 类型 UserSelect.vue
基础组件 功能名 Button.vue
弹窗组件 功能 + Form/Detail UserForm.vue

样式规范

<template>
  <!-- 优先使用 Tailwind CSS -->
  <div class="flex items-center p-4 bg-white rounded-lg">
    <span class="text-base font-medium text-gray-900">标题</span>
  </div>
</template>

<style lang="scss" scoped>
/* 组件样式使用 scoped */
.component-name {
  /* 颜色使用 CSS 变量 */
  background-color: var(--component-background);

  /* 覆盖组件库样式使用 :deep */
  :deep(.ant-table) {
    border-radius: 8px;
  }
}
</style>

注意事项

  1. 必须使用 defineOptions 定义组件名
  2. 禁止使用 any 类型
  3. Props 使用 withDefaults + defineProps<T>()
  4. 路径别名 #/* 指向 ./src/*