Skip to content

代码规范

良好的代码规范是团队协作和项目维护的基础。本章将介绍 Vue.js 项目的代码风格最佳实践。

组件命名

组件文件名

组件文件名应该始终是单词大写开头 (PascalCase):

components/
├── MyComponent.vue
├── UserProfile.vue
└── NavigationMenu.vue

组件名

在 JavaScript 中引用组件时使用 PascalCase:

javascript
import MyComponent from './MyComponent.vue'
import UserProfile from './UserProfile.vue'

在模板中使用组件时,推荐使用 kebab-case:

vue
<template>
  <my-component />
  <user-profile />
</template>

基础组件命名

基础组件(展示类的、无逻辑的或无状态的组件)应该全部以一个特定的前缀开头:

components/
├── BaseButton.vue
├── BaseTable.vue
├── BaseIcon.vue
├── AppButton.vue
├── AppTable.vue
└── AppIcon.vue

单例组件命名

只应该拥有单个活跃实例的组件应该以 The 前缀命名:

components/
├── TheHeading.vue
├── TheSidebar.vue
└── TheFooter.vue

紧密耦合的组件名

和父组件紧密耦合的子组件应该以父组件名作为前缀命名:

components/
├── TodoList.vue
├── TodoListItem.vue
├── TodoListItemButton.vue
├── UserProfileOptions.vue
└── UserProfileOptionsButton.vue

组件结构

单文件组件的顶级元素顺序

单文件组件应该总是让顶级元素的顺序保持一致:

vue
<!-- 1. template -->
<template>
  <div class="my-component">
    <!-- 组件内容 -->
  </div>
</template>

<!-- 2. script -->
<script>
export default {
  name: 'MyComponent'
}
</script>

<!-- 3. style -->
<style scoped>
.my-component {
  /* 样式 */
}
</style>

组件选项顺序

组件选项应该按照以下顺序排列:

javascript
export default {
  // 1. 全局感知 (要求在组件外的知识)
  name: 'MyComponent',
  
  // 2. 模板依赖 (模板内使用的资源)
  components: {},
  directives: {},
  
  // 3. 组合 (向选项里合并属性)
  extends: {},
  mixins: [],
  
  // 4. 接口 (组件的接口)
  inheritAttrs: false,
  props: {},
  emits: [],
  
  // 5. 组合式 API (使用组合式 API 的入口点)
  setup() {},
  
  // 6. 本地状态 (本地的响应式属性)
  data() {},
  computed: {},
  
  // 7. 事件 (通过响应式事件触发的回调)
  watch: {},
  
  // 8. 生命周期钩子 (按照它们被调用的顺序)
  beforeCreate() {},
  created() {},
  beforeMount() {},
  mounted() {},
  beforeUpdate() {},
  updated() {},
  activated() {},
  deactivated() {},
  beforeUnmount() {},
  unmounted() {},
  errorCaptured() {},
  
  // 9. 非响应式的属性 (不依赖响应式系统的实例属性)
  methods: {}
}

Props 定义

详细的 Props 定义

Props 应该尽可能详细,至少需要指定其类型:

javascript
// 不好
props: ['status']

// 好
props: {
  status: String
}

// 更好
props: {
  status: {
    type: String,
    required: true,
    validator(value) {
      return ['syncing', 'synced', 'version-conflict', 'error'].includes(value)
    }
  }
}

Prop 名大小写

在声明 prop 的时候,其命名应该始终使用 camelCase,而在模板和 JSX 中应该始终使用 kebab-case:

javascript
// JavaScript
props: {
  greetingText: String
}
vue
<!-- 模板 -->
<welcome-message greeting-text="hi" />

模板规范

模板中的表达式

模板中应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法:

vue
<!-- 不好 -->
<template>
  {{
    fullName.split(' ').map((word) => {
      return word[0].toUpperCase() + word.slice(1)
    }).join(' ')
  }}
</template>

<!-- 好 -->
<template>
  {{ normalizedFullName }}
</template>

<script>
computed: {
  normalizedFullName() {
    return this.fullName.split(' ')
      .map(word => word[0].toUpperCase() + word.slice(1))
      .join(' ')
  }
}
</script>

指令缩写

指令缩写应该要么都用要么都不用:

vue
<!-- 不好 -->
<input
  v-bind:value="newTodoText"
  :placeholder="newTodoInstructions"
>

<!-- 好 -->
<input
  :value="newTodoText"
  :placeholder="newTodoInstructions"
>

<!-- 好 -->
<input
  v-bind:value="newTodoText"
  v-bind:placeholder="newTodoInstructions"
>

多个 attribute 的元素

多个 attribute 的元素应该分多行撰写,每个 attribute 一行:

vue
<!-- 不好 -->
<img src="https://vuejs.org/images/logo.png" alt="Vue Logo">

<!-- 好 -->
<img
  src="https://vuejs.org/images/logo.png"
  alt="Vue Logo"
>

<!-- 不好 -->
<MyComponent foo="a" bar="b" baz="c" />

<!-- 好 -->
<MyComponent
  foo="a"
  bar="b"
  baz="c"
/>

JavaScript 规范

变量命名

使用有意义的变量名:

javascript
// 不好
const d = new Date()
const u = user.name
const isV = user.isValid

// 好
const currentDate = new Date()
const userName = user.name
const isUserValid = user.isValid

函数命名

函数名应该是动词或动词短语:

javascript
// 不好
function userData() {}
function userValidation() {}

// 好
function getUserData() {}
function validateUser() {}
function handleClick() {}
function fetchUserProfile() {}

常量命名

常量使用全大写字母和下划线:

javascript
const API_BASE_URL = 'https://api.example.com'
const MAX_RETRY_COUNT = 3
const DEFAULT_TIMEOUT = 5000

避免魔法数字

使用命名常量代替魔法数字:

javascript
// 不好
if (user.age >= 18) {
  // ...
}

// 好
const LEGAL_AGE = 18
if (user.age >= LEGAL_AGE) {
  // ...
}

CSS 规范

作用域样式

为组件样式设置作用域:

vue
<style scoped>
.button {
  border: none;
  border-radius: 2px;
}

.button-close {
  background-color: red;
}
</style>

CSS 类命名

使用 kebab-case 命名 CSS 类:

css
/* 不好 */
.myComponent {}
.my_component {}

/* 好 */
.my-component {}
.user-profile {}

BEM 命名规范

对于复杂组件,考虑使用 BEM 命名规范:

css
/* Block */
.card {}

/* Element */
.card__header {}
.card__body {}
.card__footer {}

/* Modifier */
.card--large {}
.card--highlighted {}
.card__header--centered {}

注释规范

组件注释

为复杂组件添加注释:

vue
<template>
  <!-- 用户头像,支持点击上传新头像 -->
  <div class="user-avatar" @click="handleAvatarClick">
    <img :src="avatarUrl" :alt="userName" />
  </div>
</template>

<script>
/**
 * 用户头像组件
 * 
 * @description 显示用户头像,支持点击上传功能
 * @author John Doe
 * @since 1.0.0
 */
export default {
  name: 'UserAvatar',
  
  props: {
    /**
     * 用户名,用于 alt 属性
     */
    userName: {
      type: String,
      required: true
    },
    
    /**
     * 头像 URL
     */
    avatarUrl: {
      type: String,
      default: '/default-avatar.png'
    }
  }
}
</script>

函数注释

为复杂函数添加 JSDoc 注释:

javascript
/**
 * 计算用户的年龄
 * 
 * @param {string} birthDate - 出生日期 (YYYY-MM-DD 格式)
 * @returns {number} 用户年龄
 * @throws {Error} 当日期格式不正确时抛出错误
 * 
 * @example
 * const age = calculateAge('1990-01-01')
 * console.log(age) // 33
 */
function calculateAge(birthDate) {
  // 实现逻辑
}

错误处理

统一错误处理

建立统一的错误处理机制:

javascript
// utils/errorHandler.js
export function handleError(error, context = '') {
  console.error(`Error in ${context}:`, error)
  
  // 发送错误到监控服务
  if (process.env.NODE_ENV === 'production') {
    // sendToErrorService(error, context)
  }
}

// 在组件中使用
export default {
  methods: {
    async fetchUserData() {
      try {
        const data = await api.getUser()
        this.userData = data
      } catch (error) {
        handleError(error, 'UserProfile.fetchUserData')
      }
    }
  }
}

代码格式化

ESLint 配置

使用 ESLint 保持代码风格一致:

javascript
// .eslintrc.js
module.exports = {
  extends: [
    'plugin:vue/vue3-essential',
    '@vue/eslint-config-prettier'
  ],
  rules: {
    'vue/multi-word-component-names': 'error',
    'vue/component-definition-name-casing': ['error', 'PascalCase'],
    'vue/component-name-in-template-casing': ['error', 'kebab-case'],
    'vue/prop-name-casing': ['error', 'camelCase']
  }
}

Prettier 配置

使用 Prettier 自动格式化代码:

json
{
  "semi": false,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5",
  "printWidth": 80,
  "bracketSpacing": true,
  "arrowParens": "avoid"
}

Git 提交规范

使用约定式提交规范:

bash
# 功能
git commit -m "feat: 添加用户头像上传功能"

# 修复
git commit -m "fix: 修复登录表单验证问题"

# 文档
git commit -m "docs: 更新 API 文档"

# 样式
git commit -m "style: 调整按钮样式"

# 重构
git commit -m "refactor: 重构用户服务模块"

# 测试
git commit -m "test: 添加用户注册测试用例"

# 构建
git commit -m "build: 更新 webpack 配置"

下一步

vue study guide - 专业的 Vue.js 学习平台