前端开发规范

一、开发工具

  1. 开发工具统一使用 VSCode
  2. 代码格式化插件使用 Prettier
  3. js代码格式校验使用 ESLint
  4. css代码格式化校验使用Stylelint
  5. VSCode 需安装的插件有:ESLint、Prettier、Stylelint、Vetur

二、命名规范

  1. 项目命名使用小写字母,以连字符分隔
    正确:fe-project
    错误:FE PROJECT、fePROJECT

  2. 目录命名使用小写字母,以连字符分隔(定义组件时除外),采用复数命名法(缩写除外)
    正确:scripts、styles、images
    错误:script、style、image

  3. 文件命名使用小写字符,以连字符分隔(定义组件时除外)
    正确:index.html、element-custom.scss
    错误:Index.html、ElementCustom.scss

  4. 组件名使用大驼峰命名
    正确:MenuItem、Upload
    错误:menu-item、upload

  5. 命名禁止使用拼音与英文混合的方式,不允许使用中文命名

三、项目结构

  1. 目录结构(以 Vue 项目为例)
    project-name
      |–node_modules 依赖
      |–public 公共文件,一般包含index.html、favicon.ico等
      |–src 源码文件目录
        |–api 接口定义目录
        |–assets 静态资源目录
        |–components 全局组件目录
        |–plugins 插件目录
        |–fonts 字体文件目录
        |–directive 自定义指令目录
        |–layout 布局文件目录
        |–icons 图标文件目录
        |–router 路由文件目录
        |–store 全局状态管理文件目录
        |–styles 样式文件目录
        |–utils 公共函数目录
        |–views|pages 页面目录
          |–SystemManage 页面组件目录(示例)
          |–components 页面内组件目录
          |–index.vue 页面文件

  2. 图片、字体等静态资源不应放在局部组件中,应放在全局目录下,组件中使用 @ 或 ~@ 引用。

四、HTML规范(适用于Vue Template)

  1. 使用 2 个空格缩进
  2. 嵌套的节点必须有缩进
  3. 不同的模块之间以空行间隔
  4. 标签必须闭合

五、CSS及其他预处理语言规范

  1. 使用2个空格缩进

  2. 不同的模块之间以空行间隔

  3. 类名使用小写字母,以连字符分隔,遵循 BEM 命名规范,使用【块__元素–修饰符】的形式命名

  4. css 中禁止使用 & 符号拼接类名
    正确:

    .form {
      .form-item {}
    }
    /* 或 */
    .form {}
    .form-item {}
    /* 仅禁止使用&拼接类名,以下使用方式不禁止 */
    .form-item {
      &.active {}
      &::before {}
      &:nth-child(1) {}
    }
    

    错误:

    .form {
      &-item {}
    }
    
  5. scss 或 less 中的变量、函数等使用小驼峰形式命名

  6. 颜色使用 16 进制小写的形式,尽量使用简写
    正确:

    color: #abcdef;
    background-color: #012;
    

    错误:

    color: #ABCDEF;
    background-color: #001122;
    
  7. css 中定义样式注意需按以下顺序
    表示元素位置的,如 position
    表示元素如何显示的,如 display
    表示元素尺寸的,如 width、height、padding
    表示元素内容样式的,如 color、font-size
    表示元素对外的状态的,如 border、box-shadow、margin

    示例:

    .box {
      position: relative;
      flex-grow: 1;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      width: 350px;
      height: 350px;
      padding: 50px;
      color: #666;
      font-size: 12px;
      text-align: center;
      background: #fff;
      border-radius: 8px;
      border: 1px solid #fff;
      box-shadow: 0px 0px 8px 4px rgba(0, 0, 0, 0.06);
      margin-bottom: 20px;
    }
    

六、JavaScript规范

  1. 使用 2 个空格缩进

  2. 单行长度不能超过 120 个字符

  3. 句尾是否添加分号不强制,但是单个项目中需统一

  4. 定义变量使用 let、const 代替 var

  5. 统一使用单引号
    正确:

    let name = 'zhangsan';
    

    错误:

    let name = "zhangsan";
    
  6. 下列关键字后必须有大括号(即使代码块的内容只有一行)
    If、else、for、while、do、switch、try、catch、finally、with
    正确:

    if (condition) {
      doSomething();
    }
    

    错误:

    if (condition) doSomething();
    
  7. 箭头函数的参数必须添加括号
    正确:

    (res) => { };
    

    错误:

    res => { };
    
  8. 对象括号与文字之间需加空格
    正确:

    { name: 'zhangsan' }
    

    错误:

    {name: 'zhangsan'}
    
  9. 对象的最后一个属性值后加逗号(单行除外)
    正确:

    const obj = {
      name: 'zhangsan',
      age: 20,
    };
    

    错误:

    const obj = {
      name: 'zhangsan',
      age: 20
    };
    
  10. 变量命名使用小驼峰的形式,不能以下划线和美元符号作为开头或结尾(特殊情况除外)

  11. 常量命名使用全大写字母的形式,单词与单词之间使用下划线分隔

  12. 构造函数名首字母大写

  13. 增删改查统一使用 add、delete、update、get 四个单词

  14. 注释符号与注释内容使用一个空格隔开
    正确:

    // 这是一段注释
    /* 这是一段注释 */
    

    错误:

    //这是一段注释
    /*这是一段注释*/
    
  15. 使用 ===、!== 代替 ==、!=

  16. 禁止使用 undefined 进行变量判断,应使用 Object.prototype.toString.call( ) 或 typeof 判断

  17. 判断变量是否为空时,优先使用 ! 或 !! 强制转为布尔类型后进行判断

  18. 创建对象时,优先使用字面量创建,而不使用对象构造器
    正确:

    const user = {
      age: 18,
      name: 'zhangsan',
    };
    

    错误:

    const user = new Object();
    user.age = 18;
    user.name = 'zhangsan';
    
  19. 对象合并时,优先使用扩展运算符,而不是 Object.assign( )
    正确:

    const obj = { ...obj1, ...obj2 };
    

    错误:

    const obj = Object.assign({}, obj1, obj2);
    
  20. 接口文件统一放在 src/api 目录中,接口文件应根据模块来定义,接口函数必须添加注释

  21. 新项目应统一使用 dayjs 作为日期处理插件

七、Vue规范

  1. 组件名应该始终是多个单词组成,且使用大驼峰的格式
  2. props 中属性必须使用小驼峰的方式命名,必须指定类型,必须加上 required 或者 default (二选一)
  3. 使用 scoped 限制组件样式作用域
  4. 需要频繁切换显示隐藏状态时,使用 v-show,而不使用 v-if
  5. methods 中定义方法,应以模块划分,相同模块的放在一起。初始化及公用的方法应放在最上方
  6. 组件标签中属性的命名使用小写字符加连字符的形式
    正确:
    <CustomComponent :custom-id="id" />
    
    错误:
    <CustomComponent :customId="id" />
    

八、项目配置

  1. 项目根目录需创建以下文件:
    .editorconfig、jsconfig.json、.prettierrc.js、.eslintrc.js、.stylelintrc.js、.prettierignore、.eslintignore、.stylelintignore

  2. VSCode 中用户的 settings.json 配置内容如下:

    {
      "files.exclude": {
        "**/.git": true,
        "**/.svn": true,
        "**/.hg": true,
        "**/CVS": true,
        "**/.DS_Store": true,
        "**/.vscode": true
      },
      "files.associations": {
        "*.wxss": "css",
        "*.wxml": "html",
        "*.wxs": "javascript"
      },
    
      "explorer.compactFolders": false,
    
      "javascript.format.enable": false,
      "javascript.updateImportsOnFileMove.enabled": "prompt",
      
      "emmet.triggerExpansionOnTab": true,
      "emmet.includeLanguages": {
      "vue-html": "html",
        "javascript": "javascriptreact"
      },
      "emmet.syntaxProfiles": {
        "javascript": "jsx"
      },
    
      "editor.tabSize": 2,
      "editor.fontSize": 16,
      "editor.wordWrap": "off",
      "editor.formatOnSave": true,
      "editor.formatOnType": true,
      "editor.detectIndentation": false,
      "editor.defaultFormatter": "esbenp.prettier-vscode",
      "editor.codeActionsOnSave": {
        "source.fixAll": false,
        "source.fixAll.stylelint": true
      },
      "stylelint.validate": ["css", "less", "postcss", "scss", "sass", "vue"],
      "stylelint.enable": true,
      
      "vetur.format.options.tabSize": 2,
      "vetur.format.defaultFormatter.js": "prettier",
      "vetur.format.defaultFormatter.html": "prettier",
      "vetur.format.defaultFormatter.scss": "prettier",
      "vetur.format.defaultFormatter.css": "prettier",
      "eslint.validate": ["javascript", "javascriptreact", "jsx", "vue", "html"],
    
      "prettier.semi": true,
      "prettier.tabWidth": 2,
      "prettier.printWidth": 120,
      "prettier.singleQuote": true,
      "prettier.trailingComma": "es5",
      "prettier.endOfLine": "lf",
      "prettier.bracketSpacing": true,
      "prettier.arrowParens": "always",
      "prettier.bracketSameLine": false,
      "prettier.singleAttributePerLine": false,
      "prettier.htmlWhitespaceSensitivity": "ignore",
    
      "[javascript]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "[jsonc]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "[html]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "[json]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "[scss]": {
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      "git.enableSmartCommit": true,
    
      "workbench.tree.indent": 16,
      "workbench.colorTheme": "Monokai",
      "workbench.startupEditor": "newUntitledFile",
      "breadcrumbs.enabled": false
    }
    
  3. 用户的 settings.json 仅作为通用配置,对于有特殊需求的项目,需配置工作区中的 settings.json。工作区的 settings.json 路径为项目根目录下的 .vscode/settings.json。注意此文件不应该被 git 忽略

  4. .editorconfig 文件配置如下

    # 告诉 EditorConfig 插件,这是根文件,不用继续往上查找
    root = true
    
    # 匹配全部文件
    [*]
    # 设置字符集
    charset = utf-8
    # 缩进风格,可选 space、tab
    indent_style = space
    # 缩进的空格数
    indent_size = 2
    # 结尾换行符,可选 lf、cr、crlf
    end_of_line = lf
    # 在文件结尾插入新行
    insert_final_newline = true
    # 删除一行中的前后空格
    trim_trailing_whitespace = true
    
    # 匹配 md 结尾的文件
    [*.md]
    insert_final_newline = false
    trim_trailing_whitespace = false
    
  5. jsconfig.json 文件配置如下

    {
      "compilerOptions": {
        "baseUrl": "./",
        "target": "ES6",
        "paths": {
          // 解决项目中使用@作为路径别名,导致vscode无法跳转文件的问题
          "@/*": ["src/*"]
        },
        // 解决prettier对于装饰器语法的警告
        "experimentalDecorators": true,
        // 解决.jsx文件无法快速跳转的问题
        "jsx": "preserve",
        "allowSyntheticDefaultImports": true
      },
      // 提高 IDE 性能
      "include": ["src/**/*"],
      "exclude": ["node_modules", "dist", "build"]
    }
    
  6. .prettierrc.js文件配置如下

    module.exports = {
      printWidth: 120, // 限制每行字符个数
      semi: false, // 句尾是否添加分号
      singleQuote: true, // 是否使用单引号
      tabWidth: 2, // 指定每个缩进级别的空格数
      useTabs: false, // 是否使用制表符缩进
      arrowParens: 'always', // 始终给箭头函数的参数加括号, // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
      trailingComma: 'es5',
      endOfLine: 'lf', // 结尾是 \n \n\r lf , auto
      bracketSpacing: true, // 在对象括号与文字之间加空格 "{ foo: bar }"
      htmlWhitespaceSensitivity: 'ignore', // "css" ignore
      bracketSameLine: false, // 将>单独一行还是在最末尾 为 true 时放在末尾
      singleAttributePerLine: true, // 标签中是否单个属性占一行,有多个属性时进行换行 为 true 时换行
    }
    
  7. .eslintrc.js文件配置如下

    module.exports = {
      root: true,
      parserOptions: {
        parser: 'babel-eslint',
        sourceType: 'module',
      },
      env: {
        browser: true,
        node: true,
        es6: true,
      },
      extends: [
        'plugin:vue/recommended',
        'eslint:recommended',
      ],
       
      // 填加自定义规则
      // 基于 (https://github.com/vuejs/eslint-config-vue)
      rules: {
        'no-var': 1, // 禁用var,用let和const代替
        'no-unused-vars': 1, // 未使用的变量
        eqeqeq: [1, 'always'], // 必须使用全等
        'vue/html-self-closing': [
          2,
          {
            html: {
              void: 'any',
              normal: 'any',
              component: 'any',
            },
            svg: 'always',
            math: 'always',
          },
        ],
        'vue/html-indent': 0,
        'vue/singleline-html-element-content-newline': 0,
      },
    };
    
  8. .stylelintrc.js文件配置如下

    module.exports = {
      extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
      plugins: ['stylelint-order'],
      overrides: [
        {
          files: ['**/*.html'],
          customSyntax: 'postcss-html',
        },
        {
          files: ['**/*.vue'],
          customSyntax: 'postcss-html',
        },
        {
          files: ['**/*.css'],
          customSyntax: 'postcss',
        },
        {
          files: ['**/*.scss'],
          customSyntax: 'postcss-scss',
        },
      ],
      rules: {
        'import-notation': null,
        'no-empty-source': null,
        'property-no-unknown': null,
        'no-descending-specificity': null,
        'selector-class-pattern': null,
        'selector-pseudo-class-no-unknown': null,
        'selector-pseudo-element-no-unknown': [
          true,
          {
            ignorePseudoElements: ['v-deep'],
          },
        ],
        'at-rule-no-unknown': [
          true,
          {
            ignoreAtRules: ['mixin', 'if', 'else'],
          },
        ],
        'color-function-notation': 'legacy',
        'media-feature-range-notation': 'prefix',
        'declaration-block-trailing-semicolon': null,
        'font-family-no-missing-generic-family-keyword': null,
        'order/order': ['custom-properties', 'declarations'],
        'order/properties-order': [
          'content',
          'position',
          'top',
          'right',
          'bottom',
          'left',
          'z-index',
    
          'float',
          'clear',
    
          'display',
          'flex-direction',
          'justify-content',
          'align-items',
          'flex',
          'flex-grow',
          'flex-shrink',
          'align-self',
    
          'table-layout',
          'box-sizing',
          'visibility',
    
          'list-style',
          'list-style-position',
          'list-style-type',
          'list-style-image',
    
          'width',
          'min-width',
          'max-width',
    
          'height',
          'min-height',
          'max-height',
    
          'padding',
          'padding-top',
          'padding-right',
          'padding-bottom',
          'padding-left',
    
          'overflow',
          'overflow-x',
          'overflow-y',
    
          'clip',
          'zoom',
    
          'font',
          'font-family',
          'font-size',
          'font-weight',
          'font-style',
          'font-variant',
          'font-size-adjust',
          'font-stretch',
          'font-effect',
          'font-emphasize',
          'font-emphasize-position',
          'font-emphasize-style',
          'font-smooth',
    
          'line-height',
          'text-align',
          'text-justify',
          'text-indent',
          'text-overflow',
          'text-decoration',
          'vertical-align',
          'white-space',
          'letter-spacing',
          'word-spacing',
          'word-wrap',
    
          'color',
    
          'opacity',
          'filter',
          'outline',
          'outline-width',
          'outline-style',
          'outline-color',
          'outline-offset',
    
          'cursor',
          'resize',
          'animation',
          'transition',
          'transform',
          'user-select',
    
          'background',
          'background-color',
          'background-image',
          'background-position',
          'background-repeat',
          'background-size',
          'background-clip',
          'background-origin',
    
          'border',
          'border-style',
          'border-width',
          'border-color',
          'border-top',
          'border-top-style',
          'border-top-width',
          'border-top-color',
          'border-right',
          'border-right-style',
          'border-right-width',
          'border-right-color',
          'border-bottom',
          'border-bottom-style',
          'border-bottom-width',
          'border-bottom-color',
          'border-left',
          'border-left-style',
          'border-left-width',
          'border-left-color',
          'border-image',
          'border-image-source',
          'border-image-slice',
          'border-image-width',
          'border-image-outset',
          'border-image-repeat',
          'border-radius',
    
          'box-shadow',
          'text-shadow',
    
          'margin',
          'margin-top',
          'margin-right',
          'margin-bottom',
          'margin-left',
        ],
      },
    }
    

    需要安装以下依赖:
    postcss、postcss-html、postcss-scss、
    stylelint、stylelint-config-prettier、stylelint-config-standard、stylelint-config-standard-scss、stylelint-order

  9. 手动格式化及校验代码需要在 package.json 中做如下配置(注意配置忽略文件 将不需要格式化的文件忽略)

    {
      "scripts": {
    	"lint": "eslint --fix --ext .js,.vue ./src",
    	"lintcss": "stylelint --fix \"src/**/*.{vue,scss,css,sass,less}\"",
        "prettier": "prettier --write ./src"
      },
     ...
    }
    

九、

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值