前端开发规范的一些实践

247 阅读3分钟

前言

现状背景

随着前端工程复杂度的不断提升,多技术栈并存、多人协作开发已成为常态。但在实际开发中,常因代码风格不统一目录结构随意组件设计缺乏约束等问题,导致代码可读性差、维护成本高、协作效率低下,甚至引发难以排查的隐性 Bug。技术债务的积累严重制约了项目的迭代效率与团队交付质量。

规范必要性

在快速迭代的业务场景下,统一的开发规范是保障项目质量的核心基础设施。它能有效解决以下问题:

  • 降低认知成本:消除团队成员对代码风格的争议,让新人快速融入
  • 提升协作效率:通过约束文件/目录/命名规则,避免"碎片化编码"现象
  • 增强可维护性:规范化的组件设计和代码逻辑,减少"牵一发而动全身"的风险
  • 控制技术债务:通过 Git 流程约束和代码审查机制,防止劣质代码进入主干

JS

格式规范

基于prettierrc规范进行配置,以VScode为例,安装prettierrc插件进行代码自动格式化,统一代码书写规范。

示例配置:

{
    "$schema": "https://json.schemastore.org/prettierrc",
    "semi": false, // 语句末尾加分号
    "tabWidth": 4, // 缩进空格数
    "singleQuote": true, // 使用单引号
    "printWidth": 200, // 单行最大长度
    "trailingComma": "none", // 多行时始终添加尾随逗号
    "bracketSameLine": true, //闭合标签与属性同行
}

变量/函数

  1. 变量名书写规范
// 变量命名(camelCase)
// 声明变量优先以const声明
const firstName = "xxx"let stuNum = "xxx"; ✅

// 常量命名(全大写,单词间用下划线分隔)
const API_KEY = "xxx"; ✅

// 私有变量(以_开头)
const _privateVar = 'xxx'// 布尔变量通常以 is, has, can 等开头
let isShow = fasle ✅
let hasPermission = falselet canEdit = true// 尽量避免语义不清晰的缩写
let userCount = 10let usrCnt = 10
  1. 函数名书写规范
// 类/构造函数
class UserProfile { ✅
  constructor(name) {
    this._privateName = name;
  }
}

// 函数 
function calculateTotalPrice(items) { ✅
  // ...
}
  1. 函数单一功能原则(SRP)
// 1. 验证用户数据
function validateUser(user) {
  if (!user.name || !user.email) {
    throw new Error("无效的用户数据");
  }
  return true;
}

// 2. 格式化用户数据
function formatUserData(user) {
  return {
    ...user,
    name: user.name.trim(),
    email: user.email.toLowerCase(),
    id: generateUserId()
  };
}

// 3. 渲染用户到DOM
function renderUserToDOM(user) {
  const userList = document.getElementById('user-list');
  const listItem = document.createElement('li');
  listItem.textContent = `${user.name} - ${user.email}`;
  userList.appendChild(listItem);
}

// 4. 保存用户数据
function saveUserToStorage(user) {
  localStorage.setItem('currentUser', JSON.stringify(user));
}

// 主函数协调各个单一职责的函数
function processUserData(user) {
  try {
    validateUser(user);
    const formattedUser = formatUserData(user);
    renderUserToDOM(formattedUser);
    saveUserToStorage(formattedUser);
  } catch (error) {
    console.error(error.message);
    // 可以添加错误处理逻辑
  }
}
//一个函数只做一件事
// 这个函数做了太多事情:验证、数据处理、DOM操作
function processUserData(user) {
  // 1. 验证
  if (!user.name || !user.email) {
    console.error("无效的用户数据");
    return;
  }
  
  // 2. 数据处理
  user.name = user.name.trim();
  user.email = user.email.toLowerCase();
  user.id = generateUserId();
  
  // 3. DOM操作
  const userList = document.getElementById('user-list');
  const listItem = document.createElement('li');
  listItem.textContent = `${user.name} - ${user.email}`;
  userList.appendChild(listItem);
  
  // 4. 保存到本地存储
  localStorage.setItem('currentUser', JSON.stringify(user));
}
  1. 逻辑判断
//建议维护一个逻辑判断常量
const TYPE_MODE = {
    ADD: 1, //新增
    DELETE: 2, //删除
    UPDATE: 3 //更新
}
//使用else if ✅
if(type === TYPE_MODE.ADD) {
    //...
}else if(type === TYPE_MODE.DELETE) {
    //...
}else if(type === TYPE_MODE.UPDATE) {
    //...
}
或 ✅
if(type === TYPE_MODE.ADD) { return; }
if(type === TYPE_MODE.DELETE) { return; }
if(type === TYPE_MODE.UPDATE) { return; }

//并列使用多个if ❌
if(type === TYPE_MODE.ADD) {}
if(type === TYPE_MODE.DELETE) {}
if(type === TYPE_MODE.UPDATE) {}

文件引入

import 文件使用绝对路径,不使用相对路径,便于代码复用及目录修改。

import { func } from @/utils/index.jsimport { func } from ../../utils/index.js

CSS

命名规范(BEM 推荐)

/* Block__Element--Modifier */
.user-card { /* 块 */ }
.user-card__header { /* 元素 */ }
.user-card--active { /* 修饰符 */ }

/* 禁止: */
.userCardHeader { /* 驼峰 ❌ */ }
.user-card-header { /* 全连字符 ❌ */ }

样式代码

充分利用样式继承,减少代码冗余。

.course-card {
    font-size: 14px;
    color: #000000;
    font-weight: 500;
    .title {
        font-size: 14px; ❌
        color: #000000; ❌
        font-weight: 400;
    }
}

禁止❌

组件中样式不使用scoped,导致全局样式污染

<style> ❌
.el-dialog { height: 100px; } 
</style>

滥用 !important

.error { color: red!important; } // 仅用于覆盖第三方样式 ❌

命名语义不清晰

.class-1: { color: #FFFFFF; } ❌

HTML

逻辑判断

复杂的逻辑判断建议使用计算属性

<template>
    <span v-if="isTransform" class="w-unit">w</span>
</template>
<script setup>
const isTransform = computed(() => {///是否需要转换w
    return props.needTransform && props.endVal >= 100000
})
</script>

组件标签

引入组件以PascalCase方式书写和使用。

<template>
    <ToolTipPro :content="name" :showArrow="true" />
</template>
<script setup>
import ToolTipPro from '@/components/ToolTipPro.vue';
</script>

禁止❌

避免行内样式过长

<div style="width: 100px; height: 50px; margin: 10px...">

拒绝无意义嵌套,尽量少的嵌套来还原设计稿

<div><span>内容</span></div>

路由规范

命名规范

  1. 路径命名使用 kebab-case 命名法(如 /user-center
  2. 路由命名使用 PascalCase 命名法(如 UserCenter
  3. 路由名与组件名保持一致
  4. 避免使用通用名称如 HomeIndex,应使用业务相关名称
// 采用标准定义格式
const routes = [
  {
    path: '/user-center',
    name: 'UserCenter', // 大驼峰命名
    component: () => import('@/views/user/UserCenter.vue'), // 懒加载
    meta: {
        title: '用户中心',
    },
    children: [...] // 嵌套路由
  }
]

路由参数

路径参(param)和查询参数(query)都使用 camelCase 命名法

// 路由跳转时传递
this.$router.push({
    name: 'HomeworkDetail',
    params: {
        homeworkId: item.homeworkId
    },
    query: {
        aiCourseId: route.query.courseId,
        aiClassId: route.query.classId,
    }
})

路由跳转

编程式导航优先

// 使用命名路由(最佳实践)✅
this.$router.push({
    name: 'UserDetail',
    params: { userId: 10012 },
    query: { from: 'home' }
})

// 避免硬编码路径
this.$router.push(`/user-detail/${userId}?from=home`) ❌

目录文件

基础结构

image.png

命名规范

4个基本原则

  1. index.js 或者 index.vue,统一使用小写字母开头的(kebab-case)命名规范
/router/index.js ✅
/components/user-card/index.vue
  1. hook文件,使用小写字母开头的(camelCase)命名规范
/hooks/useCustomMade.js
  1. 组件或类文件,统一使用大写字母开头的(PascalCase)命名规范
/layouts/DefaultLayout.vue ✅
/model/BasicNode.js
  1. 其它非组件或非类文件(包括文件夹),统一使用小写字母开头的(kebab-case)命名规范
/utils/format-date.js ✅
/pages/user-center ✅

components目录

  • 全局组件目录在src/下创建,仅此1个,用于存放全局组件。
  • 局部组件放在pages/xxx/components/,避免全局污染。
  • 基础组件加前缀Base,eg:BaseButton

Git

分支名称

分支名称以(kebab-case)命名规范,要求单词拼写完整,名称含义清晰明了,禁止使用中文,英文单词尽量不要超过3个。

分支类型

按使用场景分为6个类型:

  1. 主分支:master
  2. 发版分支:pre-master
  3. 预发环境分支:release-branch
  4. bug修复分支:fix-xxx
  5. 迭代主分支:feature-xx
  6. 功能模块开发分支:dev-xx

主分支、发版分支、预发分支为固定名称,不可变更。 bug修复分支、迭代主分支、功能模块开发分支按业务实际迭代情况进行命名。

commit信息

commit信息范式为:前缀 + : + 内容,例如 "fix:课程列表显示重复问题"。

'feat', // 新增功能

'fix', // 修复缺陷

'style', // 代码格式(不影响功能,例如空格、分号等格式修正)

'refactor',// 代码重构(不包括 bug 修复、功能新增)

'perf', // 性能优化

'build', // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)

'chore' // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)

'revert', // 回滚 commit

'docs', // 文档变更

总结

前端规范通过统一代码标准与协作流程,降低维护成本与技术债务,构建可维护、可持续的高质量工程体系。