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

---
paths:

- "**/*.vue"

Vue 组件开发规则

基于 Vue Vben Admin 项目规范。

组件结构

script setup

<script lang="ts" setup>
// 1. 组件命名(必须)
defineOptions({ name: 'ComponentName' });

// 2. 类型导入
import type { PropType } from './types';

// 3. Props 定义
interface Props {
  id: number;
  name?: string;
}

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

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

const emit = defineEmits<Emits>();

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

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

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

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

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

Props 规范

<script lang="ts" setup>
// ✅ 正确:使用 withDefaults + defineProps
interface Props {
  userId: number;
  userName?: string;
}

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

// ❌ 错误:使用运行时声明
const props = defineProps({
  userId: { type: Number, required: true },
  userName: { type: String, default: '' },
});
</script>

Emits 规范

<script lang="ts" setup>
// ✅ 正确:类型化 Emits
interface Emits {
  (e: 'update', value: string): void;
  (e: 'delete', id: number): void;
  (e: 'change', data: { id: number; name: string }): void;
}

const emit = defineEmits<Emits>();

// ❌ 错误:运行时声明
const emit = defineEmits(['update', 'delete']);
</script>

样式规范

<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;
  }
}

/* ❌ 错误:硬编码颜色 */
.bad-style {
  background-color: #ffffff;
}
</style>

组件命名

类型 命名规则 示例
页面组件 与目录名一致 UserList.vuename: 'UserList'
表单弹窗 功能 + Form UserForm.vuename: 'UserForm'
详情弹窗 功能 + Detail UserDetail.vuename: 'UserDetail'
选择器 功能 + Select UserSelect.vuename: 'UserSelect'
列表组件 功能 + List UserBomList.vuename: 'UserBomList'

导入路径

<script lang="ts" setup>
// ✅ 正确:使用 # 别名
import { getUser } from '#/api/system/user';
import DictTag from '#/components/dict-tag/dict-tag.vue';
import { useVbenForm } from '#/adapter/form';

// ✅ 正确:相对路径导入同目录
import Form from './modules/form.vue';
import { useGridColumns } from './data';
</script>

注意事项

  1. 必须使用 defineOptions 定义组件名
  2. 统一使用 <script setup lang="ts"> 语法
  3. Props 使用 withDefaults + defineProps<T>()
  4. Emits 使用 defineEmits<T>()
  5. 样式优先使用 Tailwind CSS
  6. 组件样式必须 scoped