一、开发工具
- 开发工具统一使用 VSCode
- 代码格式化插件使用 Prettier
- js代码格式校验使用 ESLint
- css代码格式化校验使用Stylelint
- VSCode 需安装的插件有:ESLint、Prettier、Stylelint、Vetur
二、命名规范
-
项目命名使用小写字母,以连字符分隔
正确:fe-project
错误:FE PROJECT、fePROJECT -
目录命名使用小写字母,以连字符分隔(定义组件时除外),采用复数命名法(缩写除外)
正确:scripts、styles、images
错误:script、style、image -
文件命名使用小写字符,以连字符分隔(定义组件时除外)
正确:index.html、element-custom.scss
错误:Index.html、ElementCustom.scss -
组件名使用大驼峰命名
正确:MenuItem、Upload
错误:menu-item、upload -
命名禁止使用拼音与英文混合的方式,不允许使用中文命名
三、项目结构
-
目录结构(以 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 页面文件 -
图片、字体等静态资源不应放在局部组件中,应放在全局目录下,组件中使用 @ 或 ~@ 引用。
四、HTML规范(适用于Vue Template)
- 使用 2 个空格缩进
- 嵌套的节点必须有缩进
- 不同的模块之间以空行间隔
- 标签必须闭合
五、CSS及其他预处理语言规范
-
使用2个空格缩进
-
不同的模块之间以空行间隔
-
类名使用小写字母,以连字符分隔,遵循 BEM 命名规范,使用【块__元素–修饰符】的形式命名
-
css 中禁止使用 & 符号拼接类名
正确:.form { .form-item {} } /* 或 */ .form {} .form-item {} /* 仅禁止使用&拼接类名,以下使用方式不禁止 */ .form-item { &.active {} &::before {} &:nth-child(1) {} }
错误:
.form { &-item {} }
-
scss 或 less 中的变量、函数等使用小驼峰形式命名
-
颜色使用 16 进制小写的形式,尽量使用简写
正确:color: #abcdef; background-color: #012;
错误:
color: #ABCDEF; background-color: #001122;
-
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规范
-
使用 2 个空格缩进
-
单行长度不能超过 120 个字符
-
句尾是否添加分号不强制,但是单个项目中需统一
-
定义变量使用 let、const 代替 var
-
统一使用单引号
正确:let name = 'zhangsan';
错误:
let name = "zhangsan";
-
下列关键字后必须有大括号(即使代码块的内容只有一行)
If、else、for、while、do、switch、try、catch、finally、with
正确:if (condition) { doSomething(); }
错误:
if (condition) doSomething();
-
箭头函数的参数必须添加括号
正确:(res) => { };
错误:
res => { };
-
对象括号与文字之间需加空格
正确:{ name: 'zhangsan' }
错误:
{name: 'zhangsan'}
-
对象的最后一个属性值后加逗号(单行除外)
正确:const obj = { name: 'zhangsan', age: 20, };
错误:
const obj = { name: 'zhangsan', age: 20 };
-
变量命名使用小驼峰的形式,不能以下划线和美元符号作为开头或结尾(特殊情况除外)
-
常量命名使用全大写字母的形式,单词与单词之间使用下划线分隔
-
构造函数名首字母大写
-
增删改查统一使用 add、delete、update、get 四个单词
-
注释符号与注释内容使用一个空格隔开
正确:// 这是一段注释 /* 这是一段注释 */
错误:
//这是一段注释 /*这是一段注释*/
-
使用 ===、!== 代替 ==、!=
-
禁止使用 undefined 进行变量判断,应使用 Object.prototype.toString.call( ) 或 typeof 判断
-
判断变量是否为空时,优先使用 ! 或 !! 强制转为布尔类型后进行判断
-
创建对象时,优先使用字面量创建,而不使用对象构造器
正确:const user = { age: 18, name: 'zhangsan', };
错误:
const user = new Object(); user.age = 18; user.name = 'zhangsan';
-
对象合并时,优先使用扩展运算符,而不是 Object.assign( )
正确:const obj = { ...obj1, ...obj2 };
错误:
const obj = Object.assign({}, obj1, obj2);
-
接口文件统一放在 src/api 目录中,接口文件应根据模块来定义,接口函数必须添加注释
-
新项目应统一使用 dayjs 作为日期处理插件
七、Vue规范
- 组件名应该始终是多个单词组成,且使用大驼峰的格式
- props 中属性必须使用小驼峰的方式命名,必须指定类型,必须加上 required 或者 default (二选一)
- 使用 scoped 限制组件样式作用域
- 需要频繁切换显示隐藏状态时,使用 v-show,而不使用 v-if
- methods 中定义方法,应以模块划分,相同模块的放在一起。初始化及公用的方法应放在最上方
- 组件标签中属性的命名使用小写字符加连字符的形式
正确:
错误:<CustomComponent :custom-id="id" />
<CustomComponent :customId="id" />
八、项目配置
-
项目根目录需创建以下文件:
.editorconfig、jsconfig.json、.prettierrc.js、.eslintrc.js、.stylelintrc.js、.prettierignore、.eslintignore、.stylelintignore -
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 }
-
用户的 settings.json 仅作为通用配置,对于有特殊需求的项目,需配置工作区中的 settings.json。工作区的 settings.json 路径为项目根目录下的 .vscode/settings.json。注意此文件不应该被 git 忽略
-
.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
-
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"] }
-
.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 时换行 }
-
.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, }, };
-
.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 -
手动格式化及校验代码需要在 package.json 中做如下配置(注意配置忽略文件 将不需要格式化的文件忽略)
{ "scripts": { "lint": "eslint --fix --ext .js,.vue ./src", "lintcss": "stylelint --fix \"src/**/*.{vue,scss,css,sass,less}\"", "prettier": "prettier --write ./src" }, ... }