前端项目架构 项目格式化规范篇

目录

一、概述

[二、VS Code设置格式化规范](#二、VS Code设置格式化规范)

1、插件推荐安装

2、Setting.json统一

三、项目中使用Prettier(推荐)

1、安装Prettier依赖

2、创建.prettierrc.cjs文件

3、创建.prettierignore文件

4、有ESLint文件可以进行配置

5、在package.json中加入命令

四、格式化

1、格式化说明

2、格式化优先级

3、格式化案例


一、概述

工欲善其事,必先利其器。在团队开发过程中,代码提交格式不统一的情况时有发生,这会导致在查看代码更新时效率降低、不便追溯。本文将针对这一问题,介绍如何构建一套有效的项目代码格式化架构。

本篇文章将从以下两个方面梳理解决方案:一是在 VS Code 中实现本地代码格式化统一,二是通过 Prettier 配置确保项目中的代码格式优先统一。

二、VS Code设置格式化规范

1、插件推荐安装

Tailwind CSS IntelliSense

Tailwind Sorter

Less IntelliSense

SCSS IntelliSense

CSS Modules

ES7+ React/Redux/React-Native snippets

React PropTypes Intellisense

React Native Tools

ESLint

Prettier - Code formatter

Path Intellisense

Error Lens

GitLess

Material Icon Theme

Solarized Light (no bold) -> Solarized Light

Project Manager

Todo Tree

Expo Tools

2、Setting.json统一

这里关键在于统一格式化属性,使用Prettier插件格式化

javascript 复制代码
{
  "workbench.settings.applyToAllProfiles": [],
  "workbench.iconTheme": "material-icon-theme",
  "diffEditor.ignoreTrimWhitespace": true,
  "react-native-tools.showUserTips": false,

  // 字体调大更护眼
  "editor.fontSize": 14,
  "editor.lineHeight": 1.6,

  // 降低对比度 - 柔和的米色主题
  "workbench.colorCustomizations": {
    "editor.background": "#f9f3e4",
    // ========== 活动栏(最左侧) ==========
    "activityBar.background": "#F7F2E7",
    "activityBar.foreground": "#666666",
    "activityBar.inactiveForeground": "#999999",
    "activityBar.border": "#E8E4DD",
    "activityBarBadge.background": "#D4C8B5",
    "activityBarBadge.foreground": "#333333",
    // ========== 侧边栏 ==========
    "sideBar.background": "#F8F6F2",
    "sideBar.foreground": "#444444",
    "sideBar.border": "#E8E4DD",
    "sideBarSectionHeader.background": "#F0EDE8",
    "sideBarTitle.foreground": "#555555",
    // ========== 标题栏 ==========
    "titleBar.activeBackground": "#F6F4F0",
    "titleBar.activeForeground": "#444444",
    "titleBar.inactiveBackground": "#F9F7F3",
    "titleBar.inactiveForeground": "#888888",
    "titleBar.border": "#E8E4DD",
    // ========== 状态栏 ==========
    "statusBar.background": "#F5F1EB",
    "statusBar.foreground": "#555555",
    "statusBar.border": "#E8E4DD",
    "statusBar.noFolderBackground": "#F5F1EB",
    "statusBar.debuggingBackground": "#E8DCC8",
    "statusBarItem.remoteBackground": "#D4C8B5",
    // ========== 标签页 ==========
    "tab.activeBackground": "#FAF9F6",
    "tab.activeForeground": "#222222",
    "tab.inactiveBackground": "#F0EDE8",
    "tab.inactiveForeground": "#666666",
    "tab.border": "#E8E4DD",
    "tab.activeBorder": "#D4C8B5",
    "tab.activeBorderTop": "#C4B8A5",
    "tab.hoverBackground": "#F5F1EB",
    "tab.unfocusedHoverBackground": "#F5F1EB",
    // ========== 编辑器组和面板 ==========
    "editorGroupHeader.tabsBackground": "#F0EDE8",
    "editorGroup.border": "#E8E4DD",
    "panel.background": "#FAF9F6",
    "panel.border": "#E8E4DD",
    "panelTitle.activeForeground": "#444444",
    "panelTitle.inactiveForeground": "#888888",
    // ========== 输入框和下拉菜单 ==========
    "input.background": "#FFFFFF",
    "input.foreground": "#333333",
    "input.border": "#E8E4DD",
    "inputOption.activeBorder": "#C4B8A5",
    "dropdown.background": "#FFFFFF",
    "dropdown.border": "#E8E4DD",
    "dropdown.foreground": "#333333",
    // ========== 按钮 ==========
    "button.background": "#D4C8B5",
    "button.foreground": "#333333",
    "button.hoverBackground": "#C4B8A5",
    "button.border": "#C4B8A5",
    // ========== 滚动条 ==========
    "scrollbar.shadow": "#E8E4DD",
    "scrollbarSlider.background": "#D4C8B599",
    "scrollbarSlider.hoverBackground": "#C4B8A599",
    "scrollbarSlider.activeBackground": "#B4A89599",
    // ========== 列表和树视图 ==========
    "list.activeSelectionBackground": "#E8E4DD",
    "list.activeSelectionForeground": "#333333",
    "list.inactiveSelectionBackground": "#F0EDE8",
    "list.hoverBackground": "#F5F1EB",
    "list.focusBackground": "#E8E4DD",
    "list.focusForeground": "#333333",
    "tree.indentGuidesStroke": "#E8E4DD",
    // ========== 通知和消息 ==========
    "notification.background": "#F7F2E7",
    "notification.foreground": "#444444",
    "notification.buttonBackground": "#D4C8B5",
    "notification.buttonHoverBackground": "#C4B8A5",
    "notification.buttonForeground": "#333333",
    "notification.infoBackground": "#E8F0E8",
    "notification.warningBackground": "#F8F0E8",
    "notification.errorBackground": "#F8E8E8",
    // ========== 其他界面元素 ==========
    "focusBorder": "#D4C8B5",
    "contrastBorder": "#E8E4DD",
    "widget.shadow": "#E8E4DD80",
    "badge.background": "#D4C8B5",
    "badge.foreground": "#333333",
    "progressBar.background": "#D4C8B5",
    // ========== 终端 ==========
    "terminal.background": "#FAF9F6",
    "terminal.foreground": "#333333",
    "terminalCursor.background": "#333333",
    "terminalCursor.foreground": "#333333",
    "terminal.ansiBlack": "#333333",
    "terminal.ansiWhite": "#FAF9F6",
    "terminal.selectionBackground": "#E8E4DD"
  },

  "workbench.colorTheme": "Solarized Light",

  // ====== 格式化相关 ======
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",

  // ====== Prettier 配置(满足您的格式化规则) ======
  "prettier.semi": true, // 1. 有分号
  "prettier.trailingComma": "none", // 2. 无尾随逗号
  "prettier.arrowParens": "avoid", // 3. 精简箭头函数(单参数无括号)
  "prettier.singleQuote": true, // 4. JS 单引号
  "prettier.jsxSingleQuote": false, // 5. JSX 双引号
  "prettier.tabWidth": 2, // 6. 2 空格缩进
  "prettier.useTabs": false, // 6. 不使用 Tab
  "prettier.endOfLine": "lf", // 7. LF 换行符
  "prettier.printWidth": 100, // 8. 每行最多 100 字符

  // ====== 语言特定配置 ======
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.tabSize": 2
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.tabSize": 2
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.tabSize": 2
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode", // 统一使用 Prettier
    "editor.tabSize": 2
  },
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.tabSize": 2
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.tabSize": 2
  },
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.tabSize": 2
  },
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.tabSize": 2
  },

  // ====== 代码编辑体验 ======
  "editor.tabSize": 2,
  "editor.insertSpaces": true,
  "editor.detectIndentation": false,
  "editor.wordWrap": "off",
  "editor.renderWhitespace": "selection",
  "editor.rulers": [100], // 显示 100 字符参考线

  // ====== ESLint 配置 ======
  "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
  "eslint.alwaysShowStatus": true,
  "eslint.codeActionsOnSave.mode": "problems",

  // ====== 文件保存 ======
  "files.autoSave": "onFocusChange",
  "files.eol": "\n", // 7. LF 换行符
  "files.trimTrailingWhitespace": true,
  "files.insertFinalNewline": true,

  // ====== 额外建议:更好地与 ESLint 集成 ======
  "prettier.eslintIntegration": false, // Prettier 3.x 已移除,使用下面配置
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.fixAll.stylelint": "explicit" // 如果需要样式检查
  },

  "files.associations": {
    "*.css": "tailwindcss"
  },
  "tailwindCSS.classAttributes": ["class", "className", "headerClassName"]
}

通过统一VS Code的setting.json来实现项目统一格式化的目的。在项目中没有使用Prettier包配置时,VS Code的setting会生效。

三、项目中使用Prettier(推荐)

1、安装Prettier依赖

bash 复制代码
# 安装 Prettier 作为开发依赖
npm install --save-dev prettier

# 或使用 yarn
yarn add --dev prettier

2、创建.prettierrc.cjs文件

javascript 复制代码
/** @type {import('prettier').Config} */
module.exports = {
  // 基础风格
  semi: true, // 有分号
  trailingComma: 'none', // 不要尾随逗号
  singleQuote: true, // 使用单引号,少按一次shift键

  // 箭头函数
  arrowParens: 'avoid', // 单参数不要括号,多参数保留

  // 代码布局
  printWidth: 100, // 每行最多100字符
  tabWidth: 2, // 缩进2个空格
  useTabs: false, // 用空格不是Tab

  // 括号处理
  bracketSpacing: true, // 对象括号内加空格 { key: value }
  bracketSameLine: true, // JSX结束标签换行

  // JSX特殊设置
  jsxSingleQuote: false, // JSX属性用双引号 <div className="test">

  // 其他
  endOfLine: 'lf', // 统一换行符(Linux/macOS风格)
  quoteProps: 'as-needed', // 只有必要时给属性加引号
  proseWrap: 'preserve', // Markdown文本保持原样

  // Next.js 相关扩展配置
  overrides: [
    {
      files: '*.{js,jsx,ts,tsx}',
      options: {
        // React/Next.js 相关优化
        parser: 'typescript',
        // 确保 JSX 属性合理换行
        jsxBracketSameLine: false,
        // 处理长链式调用
        singleAttributePerLine: false
      }
    },
    {
      files: '*.{css,scss}',
      options: {
        parser: 'css',
        singleQuote: true
      }
    },
    {
      files: '*.json',
      options: {
        parser: 'json',
        trailingComma: 'none'
      }
    },
    {
      files: '*.md',
      options: {
        parser: 'markdown',
        proseWrap: 'preserve' // Markdown 文本保持原样
      }
    }
  ],

  // 插件配置(如果有的话)
  // plugins: ['prettier-plugin-tailwindcss'],

  // 插件相关配置示例
  /*
  tailwindConfig: './tailwind.config.js',
  tailwindFunctions: ['clsx', 'cn', 'tw'],
  */

  // 格式化忽略的文件模式(也可以在 .prettierignore 中配置)
  ignorePath: '.prettierignore'
};

3、创建.prettierignore文件

javascript 复制代码
# 忽略文件
.next
node_modules
dist
build
out
public
coverage
*.log
.env*
*.local
.DS_Store
.vscode
.idea

4、有ESLint文件可以进行配置

javascript 复制代码
module.exports = {
  root: true,
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended' // 必须放在最后,关闭冲突规则
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true
    },
    ecmaVersion: 'latest',
    sourceType: 'module'
  },
  plugins: ['react', '@typescript-eslint'],
  settings: {
    react: {
      version: 'detect'
    }
  },
  rules: {
    // === 匹配你的 Prettier 偏好 ===
    semi: ['error', 'always'], // ✓ 改为有分号
    'comma-dangle': ['error', 'never'], // 无尾随逗号
    'arrow-parens': ['error', 'as-needed'], // 箭头函数括号精简

    // === React 规则 ===
    'react/react-in-jsx-scope': 'off', // React 17+ 不需要引入
    'react/prop-types': 'off', // TypeScript 项目不需要

    // === 代码质量 ===
    'no-console': 'warn',
    'no-unused-vars': 'off', // 使用 TypeScript 的规则
    '@typescript-eslint/no-unused-vars': ['error'],

    // === 简化规则 ===
    quotes: ['error', 'single'], // 单引号
    'jsx-quotes': ['error', 'prefer-double'] // JSX 双引号
  }
};

5、在package.json中加入命令

bash 复制代码
  "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx}'"

路径名称可以按照项目实际进行调整。

执行格式化脚本:

bash 复制代码
yarn run format

四、格式化

1、格式化说明

  1. 有分号 - 语句结尾加分号

  2. 无尾随逗号 - 对象/数组最后一项后不加逗号

  3. 精简箭头函数 - 单参数无括号,多参数保留括号

  4. JS 单引号 - JavaScript/TypeScript 代码用单引号

  5. JSX 双引号 - JSX 属性值用双引号

  6. 2 空格缩进 - 使用空格缩进,不用 Tab

  7. 换行符统一 - 使用 LF 换行符

  8. 代码行限制 - 每行最多 100 字符

2、格式化优先级

优先级顺序(Prettier 从高到低):

  1. 本地 .prettierrc* 配置文件

  2. package.json 中的 prettier 字段

  3. VS Code 的 prettier.* 设置

  4. Prettier 默认值

3、格式化案例

javascript 复制代码
/ ====== JavaScript/TypeScript 部分 ======

// 函数定义 - 单参数无括号
const getUser = id => {
  return { id, name: '张三' };
};

// 多参数有括号
const addUser = (name, age) => ({
  name,
  age,
  createdAt: new Date()
});

// 数组操作
const users = [
  { id: 1, name: '李四' },
  { id: 2, name: '王五' }
];

const activeUsers = users
  .filter(user => user.id > 0)
  .map(user => ({
    ...user,
    status: 'active'
  }));

// 对象定义 - 无尾随逗号
const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
  retries: 3
};

// ====== React 组件部分 ======

import React, { useState } from 'react';

const UserList = ({ users, onSelect }) => {
  const [filter, setFilter] = useState('');

  // 事件处理 - 单参数无括号
  const handleClick = userId => {
    onSelect(userId);
  };

  const handleChange = e => {
    setFilter(e.target.value);
  };

  const filteredUsers = users.filter(user => user.name.includes(filter));

  return (
    <div className="user-list">
      <input type="text" value={filter} onChange={handleChange} placeholder="搜索用户" />

      <ul>
        {filteredUsers.map(user => (
          <li key={user.id}>
            <span>{user.name}</span>
            <button onClick={() => handleClick(user.id)}>选择</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

// ====== 工具函数部分 ======

const utils = {
  // 单参数无括号
  formatDate: date => new Date(date).toLocaleDateString(),

  // 多参数有括号
  debounce: (fn, delay) => {
    let timer;
    return (...args) => {
      clearTimeout(timer);
      timer = setTimeout(() => fn(...args), delay);
    };
  }
};

// ====== 类定义部分 ======

class ApiClient {
  constructor(baseURL) {
    this.baseURL = baseURL;
  }

  // 单参数无括号
  get = async path => {
    const response = await fetch(`${this.baseURL}${path}`);
    return response.json();
  };

  // 多参数有括号
  post = async (path, data) => {
    const response = await fetch(`${this.baseURL}${path}`, {
      method: 'POST',
      body: JSON.stringify(data)
    });
    return response.json();
  };
}

// ====== 导出部分 ======

export { getUser, addUser };
export default UserList;

以上就是项目统一格式化的全部内容!

相关推荐
QQ 31316378902 小时前
文华财经软件指标公式期货买卖信号提示软件
java·前端·javascript
狂龙骄子2 小时前
svg实现蚂蚁线动画
javascript·蚂蚁线动画·蚂蚁线·虚线动画
老华带你飞2 小时前
房屋租赁管理系统|基于java+ vue房屋租赁管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
惜晨宝贝2 小时前
文件上传格式限制
前端·html5·上传测试
IT_陈寒2 小时前
Vue3性能优化实战:7个被低估的Composition API技巧让渲染提速40%
前端·人工智能·后端
颖风船3 小时前
膨胀腐蚀及底层实践,拒绝opencv,matlab等方式
前端·opencv·matlab
俩毛豆3 小时前
【毛豆工具集】【文件】【目录操作】生成沙盒目录
前端·javascript·鸿蒙
霁月的小屋3 小时前
从Vue3与Vite的区别切入:详解Props校验与组件实例
开发语言·前端·javascript·vue.js