Skip to main content

Vue 项目开发规范

一、项目结构规范

1. 基础目录结构

src/
├── api/                  # 接口请求
├── assets/               # 静态资源
│   ├── fonts/            # 字体文件
│   ├── images/           # 图片资源
│   └── styles/           # 全局样式
├── components/           # 公共组件
│   ├── common/           # 全局通用组件
│   └── business/         # 业务组件
├── composables/          # 组合式函数 (Vue3)
├── directives/           # 自定义指令
├── router/               # 路由配置
├── store/                # 状态管理
├── utils/                # 工具函数
├── views/                # 页面组件
├── App.vue               # 根组件
└── main.js               # 入口文件

2. 文件命名规范

  • 组件文件:大驼峰式 (PascalCase),如 UserInfoCard.vue
  • JS/TS文件:小驼峰式 (camelCase),如 userApi.js
  • 样式文件:短横线连接 (kebab-case),如 user-info.scss
  • 图片资源:小写+短横线,如 user-avatar.png

二、代码风格规范

1. 组件规范

<template>
  <!-- 1. 单根元素 -->
  <div class="user-card">
    <!-- 2. 组件名使用大驼峰 -->
    <UserAvatar :src="avatar" />
    
    <!-- 3. 属性多行书写 -->
    <UserInfo
      :name="user.name"
      :age="user.age"
      :gender="user.gender"
    />
  </div>
</template>

<script>
// 4. 组件名与文件名一致
export default {
  name: 'UserCard',
  // 5. 使用组件继承
  extends: BaseComponent,
  // 6. 属性定义规范
  props: {
    userId: {
      type: Number,
      required: true
    },
    showDetail: {
      type: Boolean,
      default: false
    }
  },
  // 7. 数据初始化
  data() {
    return {
      loading: false,
      user: {}
    }
  },
  // 8. 生命周期钩子顺序
  created() {},
  mounted() {},
  // 9. 方法按功能分组
  methods: {
    // 数据相关
    fetchUser() {},
    
    // UI相关
    showDetail() {}
  }
}
</script>

<style scoped>
/* 10. 使用scoped样式 */
.user-card {
  /* 11. BEM命名规范 */
  &__header {
    font-size: 16px;
  }
}
</style>

2. Vue3 Composition API 规范

<script setup>
// 1. 导入顺序:Vue > 第三方库 > 本地模块
import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import { fetchUser } from '@/api/user'
import UserAvatar from './UserAvatar.vue'

// 2. 响应式数据
const loading = ref(false)
const user = ref({})

// 3. 计算属性
const fullName = computed(() => {
  return `${user.value.firstName} ${user.value.lastName}`
})

// 4. 方法
const getUser = async () => {
  loading.value = true
  try {
    user.value = await fetchUser()
  } finally {
    loading.value = false
  }
}

// 5. 生命周期
onMounted(() => {
  getUser()
})
</script>

3. 路由规范

// router/index.js
const routes = [
  {
    path: '/user',
    name: 'User',  // 路由命名使用大驼峰
    component: () => import('@/views/User/Index.vue'),
    meta: {
      requiresAuth: true,
      title: '用户中心'
    },
    children: [
      {
        path: 'profile',
        name: 'UserProfile',
        component: () => import('@/views/User/Profile.vue')
      }
    ]
  }
]

三、状态管理规范 (Pinia/Vuex)

1. Pinia 规范

// stores/user.js
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    token: null,
    info: {}
  }),
  getters: {
    isLogin: (state) => !!state.token
  },
  actions: {
    async login(payload) {
      const res = await api.login(payload)
      this.token = res.token
      this.info = res.user
    }
  }
})

2. 使用规范

<script setup>
import { useUserStore } from '@/stores/user'

const userStore = useUserStore()

// 直接解构会失去响应性,使用storeToRefs
const { token } = storeToRefs(userStore)
</script>

四、代码提交规范

1. Git Commit 规范

<type>(<scope>): <subject>

<body>

<footer>

常用 type:

  • feat: 新功能
  • fix: 修复bug
  • docs: 文档变更
  • style: 代码格式
  • refactor: 代码重构
  • perf: 性能优化
  • test: 测试相关
  • chore: 构建/依赖变更

示例:

feat(user): add user profile page

Add new user profile page with avatar upload function

Close #123

五、最佳实践

1. 性能优化

// 1. 组件懒加载
const UserList = () => import('@/views/User/List.vue')

// 2. 图片懒加载
<img v-lazy="imageUrl" />

// 3. 长列表虚拟滚动
<VirtualList :items="largeData" />

// 4. 防抖/节流
import { debounce } from 'lodash'
methods: {
  search: debounce(function(query) {
    // 搜索逻辑
  }, 500)
}

2. 安全实践

// 1. 防止XSS
<div v-html="sanitizeHtml(content)"></div>

// 2. API请求安全
axios.interceptors.request.use(config => {
  config.headers.Authorization = `Bearer ${store.token}`
  return config
})

// 3. 路由守卫
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !store.isLoggedIn) {
    next('/login')
  } else {
    next()
  }
})

3. 错误处理

// 1. 全局错误处理
app.config.errorHandler = (err, vm, info) => {
  console.error('Vue error:', err)
  trackError(err)
}

// 2. API错误统一处理
axios.interceptors.response.use(
  response => response,
  error => {
    if (error.response.status === 401) {
      router.push('/login')
    }
    return Promise.reject(error)
  }
)

六、工具配置

1. ESLint 配置 (.eslintrc.js)

module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    '@vue/typescript/recommended'
  ],
  rules: {
    'vue/multi-word-component-names': 'off',
    'vue/component-name-in-template-casing': ['error', 'PascalCase'],
    'vue/attribute-hyphenation': ['error', 'always'],
    'vue/html-self-closing': ['error', {
      html: {
        void: 'always',
        normal: 'never',
        component: 'always'
      }
    }]
  }
}

2. Prettier 配置 (.prettierrc)

{
  "semi": false,
  "singleQuote": true,
  "printWidth": 100,
  "trailingComma": "none",
  "arrowParens": "avoid",
  "htmlWhitespaceSensitivity": "ignore"
}

以上规范可根据团队实际情况进行调整,重要的是保持团队内部的一致性。建议配合代码审查(Code Review)流程确保规范执行。