一、Vue3 通用基础规范(必看!统一编码底线)
1.1 编码格式规范:避免格式混乱,提升代码可读性
- 缩进:统一使用4个空格缩进(禁止使用Tab),确保不同编辑器渲染一致。
- 换行:每个独立代码块之间空1行,逻辑相关的代码块紧密排列,提升可读性。
- 分号:语句结尾统一添加分号,避免因自动分号插入(ASI)导致的语法歧义。
- 引号:模板内属性使用双引号(""),Script中字符串优先使用单引号(''),特殊场景(如嵌套引号)可灵活切换。
- 注释:关键逻辑、复杂业务代码必须添加注释,注释需简洁明了,说明"为什么做"而非"做了什么";组件开头可添加类注释,说明组件功能、Props、使用场景。
1.2 命名规范:一眼看懂用途,降低协作成本
核心原则:JS/TS领域遵循camelCase(小驼峰)/PascalCase(大驼峰),HTML领域使用kebab-case(连字符),保持项目内命名一致性,提升代码可读性与协作效率。
- 变量/函数:使用
camelCase,首字母小写,动词开头命名函数(如handleClick、fetchData),名词开头命名变量(如userInfo、goodsList)。 - 常量:使用
UPPER_SNAKE_CASE(全大写下划线分隔),如const API_BASE_URL = 'api.example.com'。 - 类/组件:使用PascalCase,首字母大写,组件名需为多个单词(根组件App除外),避免与HTML原生元素冲突,如UserProfile、GoodsCard而非Todo、Button。
- 自定义指令:使用
kebab-case,如v-focus、v-scroll-to,符合HTML属性命名规范。
二、Vue3 单文件组件(SFC)规范(核心重点!避坑关键)
2.1 组件结构规范:固定结构,避免渲染异常
单文件组件(.vue)内部顺序固定为:template → script → style,每个部分独立成块,结构清晰;template内最多包含一个顶级元素,避免多根节点导致的渲染异常。
xml
<!-- 正确示例 -->
<template>
<div class="user-profile">
<!-- 组件内容 -->
</div>
</template>
<script setup>
// 逻辑代码
</script>
<style scoped>
// 样式代码
</style>
2.2 Template 规范:高效渲染,减少性能损耗
- 指令使用:v-bind、v-on可使用简写(:、@),v-slot使用#简写;指令顺序统一为:v-for → v-if → v-bind → v-on,如
<div v-for="item in list" :key="item.id" v-if="item.visible" @click="handleClick">。 - v-for 要求:必须搭配key,key值需为唯一标识(如id),禁止使用index作为key;避免在v-for内使用v-if,可通过计算属性过滤数据后再渲染,提升性能。
- 组件引用:模板中使用组件时,优先使用
PascalCase标签(如),明确区分原生HTML元素;DOM模板中必须使用kebab-case(如),因HTML不区分大小写。 - 属性绑定:多个属性分行书写,每个属性占一行,提升可读性;布尔属性直接写属性名,如而非。
2.3 Script 规范:简洁高效,符合Vue3最佳实践
2.3.1 语法选择:优先<script setup>,拒绝混合语法
优先使用<script setup>语法(Vue3推荐),简洁高效;复杂组件(如需要生命周期钩子、Props验证、 emits定义)可结合Options API,但同一项目内语法需统一,禁止混合使用。
2.3.2 导入顺序:规范排序,提升代码可维护性
导入语句按以下顺序排列,不同类别之间空1行,提升可读性:
- Vue内置API(如ref、computed、watch);
- 第三方库(如Pinia、Axios、Element Plus);
- 项目内部组件(如子组件、基础组件);
- 工具函数、常量、样式文件;
- API接口请求函数。
xml
<script setup>
// 1. Vue内置API
import { ref, computed, watch } from 'vue';
// 2. 第三方库
import { useUserStore } from 'pinia';
import axios from 'axios';
// 3. 内部组件
import BaseButton from './BaseButton.vue';
import UserCard from '@/components/UserCard.vue';
// 4. 工具函数/常量
import { formatDate } from '@/utils/format';
import { API_BASE_URL } from '@/constants';
// 5. API接口
import { fetchUserInfo } from '@/api/user';
</script>
2.3.3 Props 规范:严谨定义,避免传参异常
- 命名:Props定义使用camelCase(如userName),模板中传递时使用kebab-case(如user-name),Vue会自动完成转换。
- 定义:Props需详细定义,至少指定类型;必填项标注required: true,可选值通过validator验证,提升组件可维护性与容错性。
javascript
// 正确示例
const props = defineProps({
// 基础类型定义
userId: {
type: Number,
required: true,
validator: (value) => value > 0 // 验证值为正整数
},
// 布尔类型,推荐前缀is
isDisabled: {
type: Boolean,
default: false
},
// 数组/对象类型,默认值需用函数返回,避免引用共享
goodsList: {
type: Array,
default: () => []
},
userInfo: {
type: Object,
default: () => ({
name: '',
age: 0
})
}
});
2.3.4 Emits 规范:明确声明,避免事件混乱
- 命名:定义时使用camelCase(如updateValue),模板中监听时使用kebab-case(如@update-value),符合HTML属性命名习惯。
- 定义:通过defineEmits明确声明组件触发的事件,禁止隐式触发事件;事件参数需清晰,避免传递过多参数,复杂参数建议封装为对象。
ini
// 正确示例
const emit = defineEmits(['updateValue', 'deleteItem']);
// 触发事件(传递单个参数)
const handleValueChange = (value) => {
emit('updateValue', value);
};
// 触发事件(传递复杂参数,封装为对象)
const handleDelete = (id, name) => {
emit('deleteItem', { id, name });
};
2.3.5 异步逻辑规范:优雅处理,避免报错中断
- 优先使用async/await语法,禁止使用Promise链式调用(then/catch),代码更易读且便于调试。
- 所有async/await必须包裹try/catch,或在调用时用.catch()捕获错误,避免控制台报错和逻辑中断;错误处理需友好,可结合UI提示反馈给用户。
- 高频触发的异步请求(如搜索输入框)必须加防抖,避免无效请求,推荐用组合式函数useDebounce封装复用。
javascript
// 正确示例(async/await + try/catch)
const fetchUser = async () => {
try {
const res = await fetchUserInfo(); // 调用异步接口
return res.data;
} catch (err) {
console.error('获取用户信息失败:', err);
ElMessage.error('加载失败,请重试');
throw err; // 如需上层处理,可重新抛出错误
}
};
// 错误示例(Promise链式调用)
const fetchUser = () => {
return fetchUserInfo()
.then(res => res.data)
.catch(err => {
console.error('获取用户信息失败:', err);
ElMessage.error('加载失败,请重试');
throw err;
});
};
2.3.6 TypeScript 规范:强类型约束,减少类型报错
- 禁止滥用any类型:除非明确兼容所有类型(如第三方库无类型声明),否则必须用具体类型、unknown或泛型;若用any,需加注释说明原因。
- 接口(interface)与类型别名(type)区分:定义对象/类的结构用interface(支持扩展、实现);定义联合类型、交叉类型或简单类型别名用type。
- Props/Emits 类型:使用TypeScript时,优先通过泛型定义Props和Emits类型,提升类型安全性。
typescript
// 正确示例(interface定义对象结构)
interface Goods {
id: number;
name: string;
price: number;
stock: number;
}
const goods: Goods = { id: 1, name: '手机', price: 5999, stock: 100 };
// 正确示例(type定义联合类型)
type GoodsCategory = 'electronics' | 'clothes' | 'food';
// Props类型定义
interface Props {
userId: number;
isDisabled?: boolean;
}
const props = defineProps<Props>();
// Emits类型定义
const emit = defineEmits<{
(e: 'updateValue', value: string): void;
(e: 'deleteItem', params: { id: number; name: string }): void;
}>();
2.4 Style 规范:避免污染,提升样式复用性
- 作用域:组件样式优先使用scoped(如),避免样式污染;全局样式统一放在src/styles目录下,禁止在组件内写全局样式(除非特殊需求)。
- 命名:样式类名使用kebab-case,与组件名、功能对应,如.user-profile、goods-card;避免使用无意义的类名(如box1、content2)。
- 样式顺序:按"布局 → 尺寸 → 样式 → 交互"的顺序编写,如position → width → background → hover。
- 复用:公共样式(如颜色、字体、间距)提取为变量,统一管理;重复使用的样式封装为Mixin或自定义样式类,提升复用性。
三、Vue3 组件设计规范(高复用+低耦合,团队必守)
3.1 组件拆分原则:拒绝大组件,提升可维护性
- 单一职责:一个组件只负责一个功能,避免"大组件"(代码超过500行),复杂功能拆分为多个子组件,如将用户列表拆分为UserList(列表容器)、UserItem(列表项)、UserSearch(搜索框)。
- 高复用低耦合:可复用组件(如按钮、输入框)提取为基础组件(放在src/components/base目录),组件间通过Props传递数据、Emits触发事件,禁止直接操作父/子组件数据。
- 命名区分:基础组件统一前缀Base(如BaseButton、BaseInput),业务组件按功能命名(如OrderList、PaymentForm),布局组件前缀Layout(如LayoutHeader、LayoutSidebar)。
3.2 组件通信规范:清晰传参,避免数据混乱
- 父子组件:父传子用Props,子传父用Emits,禁止子组件直接修改Props(单向数据流);复杂数据可通过v-model双向绑定(Vue3支持多v-model)。
- 跨层级组件:优先使用Pinia状态管理,或使用provide/inject(适用于深层组件通信,需明确注入类型),禁止使用EventBus(易造成事件混乱)。
- 同级组件:通过父组件中转(子传父 → 父传另一个子),或使用Pinia共享状态,避免直接通信。
四、Vue3 Pinia 状态管理规范(替代Vuex,简洁高效)
4.1 Store 设计原则:模块化拆分,避免冗余
- 模块化:按业务模块拆分Store(如userStore、cartStore、goodsStore),避免单一Store过大;Store命名统一前缀use(如useUserStore),使用camelCase命名法。
- 状态划分:State(状态)、Getters(计算属性)、Actions(异步/同步操作)分离,禁止在Getters中修改State,禁止在组件中直接修改Store的State(需通过Actions)。
4.2 状态操作规范:规范调用,避免状态异常
ini
// stores/user.ts 正确示例
import { defineStore } from 'pinia';
import { fetchUserInfo } from '@/api/user';
export const useUserStore = defineStore('user', () => {
// State:定义状态,使用ref/reactive
const userInfo = ref({
id: 0,
name: '',
avatar: ''
});
const isLogin = ref(false);
// Getters:计算属性,依赖State,只读
const userNickname = computed(() => userInfo.value.name || '未知用户');
// Actions:处理同步/异步操作,修改State
const setUserInfo = (info) => {
userInfo.value = info;
isLogin.value = true;
};
const logout = () => {
userInfo.value = { id: 0, name: '', avatar: '' };
isLogin.value = false;
};
// 异步Action,使用async/await
const loadUserInfo = async (userId) => {
try {
const res = await fetchUserInfo(userId);
setUserInfo(res.data);
} catch (err) {
console.error('加载用户信息失败:', err);
throw err;
}
};
return { userInfo, isLogin, userNickname, setUserInfo, logout, loadUserInfo };
});
五、Vue3 Vue Router 路由规范(优化体验,避免路由踩坑)
- 路由命名:路由name使用kebab-case(如user-profile),与组件名、路径对应,提升可读性;路由path使用kebab-case(如/user/profile),符合URL命名规范。
- 路由懒加载:所有路由组件均使用懒加载(() => import('组件路径')),减少首屏加载时间;基础组件无需懒加载。
- 路由守卫:全局守卫用于权限控制(如登录验证),路由独享守卫用于单个路由的特殊控制,组件内守卫用于组件内的生命周期控制;避免在守卫中写复杂业务逻辑。
- 参数传递:路径参数(params)用于必填参数(如/user/:id),查询参数(query)用于可选参数(如/list?page=1&size=10);接收参数时需做类型校验。
javascript
// router/index.ts 正确示例
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/',
name: 'home',
component: () => import('@/views/Home.vue'),
meta: { title: '首页', requiresAuth: false }
},
{
path: '/user/:id',
name: 'user-profile',
component: () => import('@/views/UserProfile.vue'),
meta: { title: '用户详情', requiresAuth: true },
props: true // 自动将params转为Props传递给组件
},
{
path: '/404',
name: '404',
component: () => import('@/views/404.vue')
},
{
path: '/:pathMatch(.*)*',
redirect: '/404' // 路由匹配失败,重定向到404
}
];
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
});
// 全局前置守卫:登录验证
router.beforeEach((to, from, next) => {
const userStore = useUserStore();
if (to.meta.requiresAuth && !userStore.isLogin) {
next('/login');
} else {
document.title = to.meta.title || 'Vue3 项目';
next();
}
});
export default router;
六、Vue3 工程化与协作规范(团队高效协作必备)
6.1 文件目录规范:结构清晰,便于维护
项目目录结构清晰,按功能模块划分,便于维护和协作,推荐目录结构如下:
scss
src/
├── assets/ // 静态资源(图片、字体、图标等),命名使用kebab-case
│ ├── images/
│ ├── fonts/
│ └── icons/
├── components/ // 公共组件
│ ├── base/ // 基础组件(BaseButton、BaseInput等)
│ ├── layout/ // 布局组件(LayoutHeader、LayoutSidebar等)
│ └── business/ // 业务组件(OrderList、GoodsCard等)
├── views/ // 页面视图组件,命名使用PascalCase
│ ├── Home.vue
│ ├── UserProfile.vue
│ └── Order/
│ ├── OrderList.vue
│ └── OrderDetail.vue
├── stores/ // Pinia状态管理,命名使用useXXXStore.ts
│ ├── useUserStore.ts
│ └── useCartStore.ts
├── router/ // 路由配置
│ └── index.ts
├── api/ // API接口封装,按模块划分
│ ├── user.ts
│ └── goods.ts
├── utils/ // 工具函数,命名使用camelCase
│ ├── format.ts
│ └── request.ts
├── constants/ // 常量定义
│ └── index.ts
├── styles/ // 全局样式
│ ├── index.scss
│ └── variables.scss
├── composables/ // 组合式函数,复用逻辑
│ └── useDebounce.ts
└── App.vue // 根组件
6.2 代码提交规范(Git Commit):清晰可追溯,便于审查
采用Conventional Commits标准,提交信息清晰,便于代码审查和版本回溯,格式为:(): 。
- type(提交类型):feat(新功能)、fix(Bug修复)、docs(文档变更)、style(代码样式调整,不影响逻辑)、refactor(重构,不修复Bug也不增加功能)、test(测试相关)、chore(构建/工具变更)。
- scope(范围):指定提交影响的模块(如user、router、goods),无明确范围可省略。
- subject(描述):简洁明了,说明提交内容,首字母小写,结尾不加句号。
scss
// 示例
feat(user): add password reset UI
fix(router): handle 404 redirect
chore(deps): upgrade axios to 1.2.0
docs: update component usage documentation
6.3 代码校验规范:统一格式,减少冲突
- 工具配置:项目必须集成ESLint、Prettier,统一代码格式;安装依赖:npm install -D eslint prettier eslint-plugin-vue @typescript-eslint/parser eslint-config-prettier husky lint-staged。
- 自动校验:配置pre-commit钩子(husky + lint-staged),提交代码时自动校验格式,不符合规范的代码禁止提交;开发过程中使用编辑器插件(如ESLint、Prettier)实时校验。
- ESLint配置:继承vue3-recommended规范,结合项目需求调整规则,禁止禁用必要的校验规则(如禁止滥用any、禁止Props修改)。
七、Vue3 性能与安全规范(优化体验+规避风险)
7.1 性能优化规范:提速降耗,提升用户体验
- 响应式优化:避免过度使用reactive,简单数据使用ref;大数据列表使用v-virtual-scroller(虚拟滚动),减少DOM渲染数量。
- 计算属性与监听:computed用于依赖状态的计算(缓存结果),watch用于监听状态变化并执行副作用(如请求接口);避免在watch中写复杂逻辑,避免监听过多状态。
- 资源优化:静态资源(图片)压缩,使用CDN加载;路由懒加载、组件懒加载;避免重复请求(添加请求缓存、防抖节流)。
- DOM优化:减少DOM操作,避免在模板中使用复杂表达式;使用v-show替代v-if(频繁切换场景),v-if替代v-show(一次性渲染场景)。
7.2 安全规范:规避漏洞,保障项目稳定
- XSS防护:避免直接插入HTML(如v-html),若必须使用,需对内容进行过滤;禁止使用eval、with等危险语法。
- 接口安全:请求接口时添加token验证;敏感数据(如密码)加密后传输;接口返回数据需做类型校验,避免恶意数据导致的报错。
- 依赖安全:定期更新项目依赖,避免使用存在安全漏洞的依赖包;安装依赖前检查依赖安全性(如使用npm audit)。
八、Vue3 补充规范(细节拉满,避免踩坑)
- 兼容性:兼容主流浏览器(Chrome、Edge、Firefox最新版本),如需兼容旧浏览器(如IE11),需添加相应的polyfill。
- 可维护性:代码书写简洁,避免冗余(如重复代码封装为函数/组件);注释清晰,便于后续维护和他人理解。
- 一致性:项目内所有代码严格遵循本规范,团队成员需统一认知;新增规范需团队讨论确认后补充,避免个人风格差异导致的代码混乱。
- 废弃代码:禁止保留无用代码(如注释掉的代码、未使用的变量/函数/组件),提交代码前删除废弃内容,保持代码整洁。