🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 天马工场前端代码规范 # 一、编程规约 ### (一)命名规范 #### 1.1.1 项目命名 全部采用小写方式, 以中划线分隔。 正例:`mall-management-system` 反例:`mall_management-system / mallManagementSystem` #### 1.1.2 目录命名 全部采用小写方式, 以中划线分隔,有复数结构时,要采用复数命名法, 缩写不用复数 正例: `scripts / styles / components / images / utils / layouts / demo-styles / demo-scripts / img / doc` 反例: `script / style / demo_scripts / demoStyles / imgs / docs` #### 1.1.3 JS、CSS、SCSS、HTML、PNG 文件命名 全部采用小写方式, 以中划线分隔 正例: `render-dom.js / signup.css / index.html / company-logo.png` 反例: `renderDom.js / UserManagement.html` 不要在文件名后加数字, 来实现相同功能的多个版本 如:drag1.js、drag2.js、drag3.js是禁止的。 #### 1.1.4 命名严谨性 代码中的命名严禁使用拼音与英文混合的方式。 说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义,好的命名比注释更有用。 **杜绝完全不规范的缩写,避免望文不知义:** 正例:hor / vert / arr / temp / str / reg / lens 等。 反例:AbstractClass“缩写”命名成 AbsClass;condition“缩写”命名成 condi,此类随意缩写严重降低了代码的可阅读性。 ### (二)HTML 规范 #### 1.2.1 HTML 类型 推荐使用 HTML5 的文档类型申明: <!DOCTYPE html>. 正例: ```html <!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <meta charset="UTF-8" /> <title>Page title</title> </head> <body> <img src="images/company-logo.png" alt="Company" /> </body> </html> ``` #### 1.2.2 缩进 缩进使用 2 个空格(一个 tab) 嵌套的节点应该缩进。 #### 1.2.3 分块注释 在每一个块状元素,列表元素和表格元素后,加上一对 HTML 注释。注释格式 `<!-- 英文 中文 start >` `<!-- 英文 中文 end >` 正例: ```html <body> <!-- header 头部 start --> <header> <div class="container"> <a href="#"> <img src="images/header.jpg" /> </a> </div> </header> <!-- header 头部 end --> </body> ``` #### 1.2.4 换行 标签属性过多时需要换行对齐,方便阅读。 正例: ```html <Pagination total={total} pageSizeOptions={["10", "20", "40"]} showTotal={(total) => `共${total}条数据`} onChange={onChange} current={current} onShowSizeChange={onShowSizeChange} showSizeChanger showQuickJumper /> ``` 反例: ```html <Pagination total={total} pageSizeOptions={["10", "20", "40"]} showTotal={(total) => `共${total}条数据`} onChange={onChange} current={current} onShowSizeChange={onShowSizeChange} showSizeChanger showQuickJumper /> ``` #### 1.2.5 语义化标签 HTML5 中新增很多语义化标签,所以优先使用语义化标签,避免一个页面都是 div 或者 p 标签 正例 ```html <header></header> <footer></footer> <title></title> <hn></hn> <main></main> <p></p> ... ``` 反例 ```html <div> <div></div> </div> ``` #### 1.2.6 引号 使用双引号(" ") 而不是单引号(' ') 。 正例: `<div class="news-div"></div>` 反例: `<div class='news-div'></div>` ### (三) CSS 规范 #### 1.3.1 命名 - 类名使用小写字母,以中划线分隔 - id 采用驼峰式命名 - scss 中的变量、函数、混合采用驼峰式命名 ID 和 class 的名称总是使用可以反应元素目的和用途的名称,或其他通用的名称,代替表象和晦涩难懂的名称 反例: ```css .fw-800 { font-weight: 800; } .red { color: red; } ``` 正例: ```css .heavy { font-weight: 800; } .important { color: red; } ``` #### 1.3.2 选择器 1)css 选择器中避免使用标签名 从结构、表现、行为分离的原则来看,应该尽量避免 css 中出现 HTML 标签,并且在 css 选择器中出现标签名会存在潜在的问题。 2)很多前端开发人员写选择器链的时候不使用 直接子选择器(注:直接子选择器和后代选择器的区别)。有时,这可能会导致疼痛的设计问题并且有时候可能会很耗性能。然而,在任何情况下,这是一个非常不好的做法。如果你不写很通用的,需要匹配到 DOM 末端的选择器, 你应该总是考虑直接子选择器。 反例: ```css .content .title { font-size: 2rem; } ``` 正例: ```css .content > .title { font-size: 2rem; } ``` #### 1.3.3 尽量使用缩写属性 反例: ```css border-top-style: none; font-family: palatino, georgia, serif; font-size: 100%; line-height: 1.6; padding-bottom: 2em; padding-left: 1em; padding-right: 1em; padding-top: 0; ``` 正例: ```css border-top: 0; font: 100%/1.6 palatino, georgia, serif; padding: 0 1em 2em; ``` #### 1.3.4 每个选择器及属性独占一行 反例: ```css button { width:100px;height:50px;color:#fff;background:#00a0e9; } ``` 正例: ```css button { width:100px; height:50px; color:#fff; background:#00a0e9; } ``` #### 1.3.5 省略0后面的单位 反例: ```css div { padding-bottom: 0px; margin: 0em; } ``` 正例: ```css div { padding-bottom: 0; margin: 0; } ``` **小数点前面的0也可以省略,0.7 写成 .7** #### 1.3.6 避免使用ID选择器及全局标签选择器防止污染全局样式 反例: ```css #header { padding-bottom: 0px; margin: 0em; } ``` 正例: ```css .header { padding-bottom: 0px; margin: 0em; } ``` ### (四) LESS/SASS 规范 #### 1.4.1 代码组织 ##### 1)将公共less, scss文件放置在styles文件夹 例:// color.less, common.less, mixin.less, variables.less ##### 2)按以下顺序组织 1、@import; 2、变量声明; 3、样式声明; ```css @import "mixins.less"; @default-text-color: #333; .page { width: 960px; margin: 0 auto; } ``` #### 1.4.2 避免嵌套层级过多 将嵌套深度限制在3级。对于超过4级的嵌套,给予重新评估。这可以避免出现过于详实的CSS选择器。 避免大量的嵌套规则。当可读性受到影响时,将之打断。推荐避免出现多于20行的嵌套规则出现 反例: ```css .main { .title { .name { color:#fff } } } ``` 正例: ```css .main-title { .name { color:#fff } } ``` #### 1.4.3 每个类之间敲个回车 css一旦多,会显的过于臃肿,适当隔开便于阅读。 反例: ```css .main { width:100px; height:50px; color:#fff; background:#00a0e9; .name { color:#fff } .title { background: #ccc } &:hover { font-size: 12px } } ``` 正例: ```css .main { width:100px; height:50px; color:#fff; background:#00a0e9; .name { color:#fff } .title { background: #ccc } &:hover { font-size: 12px } } ``` ### (五) Javascript 规范 #### 1.5.1 命名 ##### 1) 采用小写驼峰命名 lowerCamelCase,代码中的命名均不能以下划线,也不能以下划线或美元符号结束 反例: `_name / name_ / name$` \***\*其中_通常表示私有的意思\*\*** ##### 2) 方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式。 正例: `localValue / getHttpMessage() / inputUserId` \***\*其中 method 方法命名必须是 动词 或者 动词+名词 形式\*\*** 正例:`saveShopCarData /openShopCarInfoDialog` 反例:`save / open / show / go` \***\*特此说明,增删查改,详情统一使用如下 5 个单词,不得使用其他(目的是为了统一各个端)\*\*** `add / update / delete / detail / get` **附: 函数方法常用的动词:** ```js get 获取/set 设置, add 增加/remove 删除 create 创建/destory 移除 start 启动/stop 停止 open 打开/close 关闭, read 读取/write 写入 load 载入/save 保存, create 创建/destroy 销毁 begin 开始/end 结束, backup 备份/restore 恢复 import 导入/export 导出, split 分割/merge 合并 inject 注入/extract 提取, attach 附着/detach 脱离 bind 绑定/separate 分离, view 查看/browse 浏览 edit 编辑/modify 修改, select 选取/mark 标记 copy 复制/paste 粘贴, undo 撤销/redo 重做 insert 插入/delete 移除, add 加入/append 添加 clean 清理/clear 清除, index 索引/sort 排序 find 查找/search 搜索, increase 增加/decrease 减少 play 播放/pause 暂停, launch 启动/run 运行 compile 编译/execute 执行, debug 调试/trace 跟踪 observe 观察/listen 监听, build 构建/publish 发布 input 输入/output 输出, encode 编码/decode 解码 encrypt 加密/decrypt 解密, compress 压缩/decompress 解压缩 pack 打包/unpack 解包, parse 解析/emit 生成 connect 连接/disconnect 断开, send 发送/receive 接收 download 下载/upload 上传, refresh 刷新/synchronize 同步 update 更新/revert 复原, lock 锁定/unlock 解锁 check out 签出/check in 签入, submit 提交/commit 交付 push 推/pull 拉, expand 展开/collapse 折叠 begin 起始/end 结束, start 开始/finish 完成 enter 进入/exit 退出, abort 放弃/quit 离开 obsolete 废弃/depreciate 废旧, collect 收集/aggregate 聚集 ``` ##### 3) 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。 正例: `MAX_STOCK_COUNT` 反例: `MAX_COUNT` #### 1.5.2 代码格式 ##### 1) 使用 2 个空格进行缩进 正例: ```js if (x < y) { x += 10; } else { x += 1; } ``` ##### 2) 不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。 说明:任何情形,没有必要插入多个空行进行隔开。 #### 1.5.3 字符串 统一使用单引号(‘),不使用双引号(“)。这在创建 HTML 字符串非常有好处: 正例: ```js let str = 'foo'; let testDiv = '<div id="test"></div>'; ``` 反例: ```js let str = 'foo'; let testDiv = "<div id='test'></div>"; ``` #### 1.5.4 使用 ES6+ 必须优先使用 ES6+ 中新增的语法糖和函数。这将简化你的程序,并让你的代码更加灵活和可复用。 比如箭头函数,await/async,解构(数组解构,对象解构,参数解构),参数默认值,数组新增方法,对象新增方法等等。 #### 1.5.5 括号 下列关键字后必须有大括号(即使代码块的内容只有一行):if, else, for, while, do, switch, try, catch, finally。 正例: ```js if (condition) { doSomething(); } ``` 反例: ```js if (condition) doSomething(); ``` #### 1.5.6 条件判断和循环最多三层 条件判断能使用三目运算符和逻辑运算符解决的,就不要使用条件判断,但是谨记不要写太长的三目运算符。如果超过 3 层请抽成函数,并写清楚注释。 #### 1.5.7 this 的转换命名 对上下文 this 的引用只能使用'self'来命名。 #### 1.5.8 慎用 console.log 因 console.log 大量使用会有性能问题,所以在非 webpack 项目中谨慎使用 log 功能。 上线之前必须删除所有的console.log。 #### 1.5.9 空格 ##### 需要保留空格的情况: ##### 1) 各种运算符, 包括数值操作符(例如:+、-、*、/、%等)、位运算符、比较运算符、三元运算符、复合赋值运算符、赋值运算符前后, 保留一个空格。 “.”(点) 和“(”(左括号)和 “[”(左方括号)例外。 反例: ```js let a=b+c; let a=isFlag?1:2; ``` 正例: ```js let a = b + c; let a = isFlag ? 1 : 2; ``` ##### 2) for 循环条件中, 分号后保留一个空格。 反例: ```js for(let i=0;i<lens;i++){} ``` 正例: ```js for(let i = 0; i < lens; i++){} ``` ##### 3) 所有的逗号后保留一个空格, 例如: 变量声明语句、数组值、JSON 对象值、函数参数值等等。 反例: ```js const arr=[1,2,3]; ``` 正例: ```js const arr = [1, 2, 3]; ``` ##### 4) 冒号后加空格。 反例: ```js const obj = { name:'lucy', age:18 }; ``` 正例: ```js const obj = { name: 'lucy', age: 18 }; ``` ##### 5) if / else / for / while / function / switch / do / try / catch / finally 关键字后,必须有一个空格。 ##### 6) 函数调用的括号“(”前, 要出现空格。 ##### 7) 注释符前后要有空格。 ##### 不需要保留空格的情况: ##### 1) 一元操作符与其操作数之间不应有空格, 如: i++。除非操作符是个单词, 例如: typeof window。 ##### 2) 点号前后不要出现空格。 ##### 3) 空行不要有空格, 尾不要有空格。 ##### 4) 空对象和数组不需要填入空格。[], {} #### 1.5.10 回车(换行) ##### 1) 每个独立语句结束后必须换行。超长的不可分割的代码允许例外,比如复杂的正则表达式。长字符串不在例外之列。 ##### 2) 运算符处换行时,运算符必须在新行的行首。 正例: ```js if (user.isAuthenticated() && user.isInRole('admin') && user.hasAuthority('add-admin') || user.hasAuthority('delete-admin') ) { // Code } let result = number1 + number2 + number3 + number4 + number5; ``` 反例: ```js if (user.isAuthenticated() && user.isInRole('admin') && user.hasAuthority('add-admin') || user.hasAuthority('delete-admin')) { // Code } var result = number1 + number2 + number3 + number4 + number5; ``` ##### 2) 不同行为或逻辑的语句集,使用空行隔开,更易阅读。 比如: ```js // 仅为按逻辑换行的示例,不代表setStyle的最优实现 function setStyle(element, property, value) { if (element == null) { return; } element.style[property] = value; } ``` ##### 3) 在语句的行长度超过 120 时,根据逻辑条件合理缩进。 #### 1.5.11 注释 ##### 1) 单行注释:必须独占一行。// 后跟一个空格,缩进与下一行被注释说明的代码一致。在注释前插入空行。 正例: ```js function getType() { console.log('fetching type...'); // set the default type to 'no type' const type = this._type || 'no type'; return type; } ``` 反例: ```js function getType() { console.log('fetching type...'); // set the default type to 'no type' const type = this._type || 'no type'; return type; } ``` ##### 2) 多行注释:避免使用 /*...*/ 这样的多行注释。有多行注释内容时,使用多个单行注释。 ##### 3) 文档化注释:为了便于代码阅读和自文档化,内容必须包含以 /**...*/ 形式的块注释中。文档注释前必须空一行。 比如: ```js /** * make() returns a new element * based on the passed in tag name * * @param {String} tag * @return {Element} element */ function make(tag) { // ...stuff... return element; } ``` ##### 4) 注释中定义类型:常用类型{string}, {number}, {boolean}, {Object}, {Function}, {RegExp}, {Array}, {Date}。 ##### 5) TODO注释:原则上需要删除无用的注释代码,确实不能删除,需要加 TODO: 写明原因。或者其他想特别说明的(比如现在是临时解决办法)也可以用TODO写明。 比如: ```js class Calculator { constructor() { // TODO: total should be configurable by an options param this.total = 0; } } ``` **避免过度注释,定义一个好的变量,方法,类名,比注释更好** 注释原则 复杂的代码: 复杂业务/使用了难以理解的技术,取巧的实现方法 妥协的代码: 设计不好,但是为了实现业务又暂时没有其他更好选择 兼容性代码: 向下/平台兼容代码最好注释,避免误删 #### 1.5.12 条件 ##### 1) 在 Equality Expression 中使用类型严格的 === 或者 !==。仅当判断 null 或 undefined 时,允许使用 == null。 正例: ```js if (age === 30) { // ...... } ``` 反例: ```js if (age == 30) { // ...... } ``` ##### 2) 尽可能使用简洁的表达式。 ```js if (!name) { // ...... } if (collection.length) { // ...... } ``` 反例: ```js if (name === '') { // ...... } if (collection.length > 0) { // ...... } ``` ##### 3) 如果函数或全局中的 else 块后没有任何语句,可以删除 else。 #### 1.5.13 循环 ##### 1) 对有序集合进行遍历时,缓存 length 正例: ```js for (var i = 0, len = elements.length; i < len; i++) { var element = elements[i]; // ...... } ``` 反例: ```js for (var i = 0; i < elements.length; i++) { var element = elements[i]; // ...... } ``` #### 1.5.14 字符串模板 ##### 1) 带有变量的字符串,使用字符串模版 正例: ```js const name = 'lucy' const greetings = `Hello ${name}` ``` 反例: ```js const name = 'lucy' const greetings = 'Hello ' + name ``` ##### 2) 换行的字符串 ```js const html = ` <article> <h1>Title here</h1> <p>This is a paragraph</p> <footer>Complete</footer> </article> ` ``` #### 1.5.15 数组 ##### 1) 简单数组(对象),使用扩展运算符(spread operator)... 复制数组(浅拷贝) 正例: ```js const list = [1, 2, 3] const result = [...list] ``` 反例: ```js const list = [1, 2, 3] const result = list.concat() ``` ##### 2) 充分使用数组方法,map, find, filter, foreach 等方法。 #### 1.5.16 对象 ##### 1) 简写的属性放在前面 正例: ```js const obj = { lukeSkywalker, anakinSkywalker, episodeOne: 1, twoJediWalkIntoACantina: 2, episodeThree: 3, mayTheFourth: 4 } ``` 反例: ```js const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, mayTheFourth: 4, anakinSkywalker } ``` ##### 2) 使用 . 来访问对象的属性。当通过变量访问属性时使用中括号 []。 正例: ```js const obj = { name: 'lucy', age: 18 } const name = obj.name function getProp(prop) { return obj[prop]; } const name = getProp('name'); ``` 反例: ```js const obj = { name: 'lucy', age: 18 } const name = obj['name'] ``` ##### 3) 对象的属性和方法,尽量采用简洁表达法,这样易于描述和书写。 正例: ```js const atom = { value: 1, addValue(value) { return atom.value + value; }, }; ``` 反例: ```js const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; ``` #### 1.5.17 变量 ##### 1) 避免使用全局变量 ##### 2) 使用 let 代替 var ##### 3) 使用 const 声明常量 正例: ```js // good const a = 1; const b = 2; const c = 3; // best const [a, b, c] = [1, 2, 3]; ``` 反例: ```js var a = 1, b = 2, c = 3; ``` ##### 4) 删除未使用的变量(方法) ##### 5) 多次使用的命名空间,使用对象解构替换,简洁易读 正例: ```js const { x, y } = obj const [a, b] = arr function getFullName(obj) { const { firstName, lastName } = obj; return `${firstName} ${lastName}`; } 或者参数解构 function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; } ``` 反例: ```js const x = obj.x const y = obj.y const a = arr[0] const b = arr[1] function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}`; } ``` #### 1.5.18 模块 模块导入导出使用标准语法 import export 导入模块需要分类排列,比如第三方模块 自有模块等 每个模块不宜过大,最大行数控制在400行左右,过大可以重新考虑模块的划分 #### 1.5.19 定时器 定时器(setInterval或者setTimeout)的变量, 使用完后必须显式销毁, 从而可以及时的执行内存回收。 请执行 clearInterval 或者 clearTimeout。 #### 1.5.20 警告 eslint的警告需要处理,暂时不能处理的可以用 // eslint-disable-next-line 过滤 ### (六) React 项目目录结构 #### 1.6.1 目录结构 ```bash ├─ public # 静态资源 │ ├─ favicon.ico # favicon图标 │ └─ index.html # html模板 ├─ src # 项目源代码 │ ├─ api # 所有请求接口 │ ├─ assets # 图片 字体等静态资源 │ ├─ components # 全局公用组件 │ ├─ config # 全局配置 │ │ ├─ menuConfig.js # 导航菜单配置 │ │ └─ routeMap.js # 路由配置 │ ├─ lib # 第三方库按需加载(需要就有,不需要就删除) │ ├─ store # 全局 store管理 │ ├─ styles # 全局样式 │ ├─ utils # 全局公用方法 │ ├─ views # views 所有页面 │ ├─ App.js # 入口页面 │ ├─ setupProxy.js # 服务器地址用于解决本地开发跨域问题 │ └─index.js # 源码入口 ├── .env.development # 开发环境变量配置 ├── .env.production # 生产环境变量配置 ├── config-overrides.js # webpack自定义配置 ├── deploy.sh # CI部署脚本 ├── .travis.yml # 自动化CI配置 ├── .gitignore # 提交git需要忽略的文件 └── package.json # 依赖的包配置文件 ``` #### 1.6.2 项目启动方式 ```shell # 安装依赖 npm install 或者 yarn # 切换淘宝源,解决 npm 下载速度慢的问题 npm install --registry=https://registry.npm.taobao.org # 启动服务 npm start ``` ### (七) Vue 项目目录结构 #### 1.7.1 目录结构 ```bash ├─ config │ ├─ dev.env.js # 开发环境配置 │ ├─ index.js # 运行及打包模版配置 │ ├─ prod.env.js # 正式环境配置 ├─ src # 项目源代码 │ ├─ api # 所有请求接口 │ ├─ assets # 图片 字体等静态资源 │ ├─ components # 全局公用组件 │ ├─ router # 路由配置 │ ├─ store # 全局 store管理 │ ├─ styles # 全局样式 │ ├─ utils # 全局公用方法 │ ├─ views # views 所有页面 │ ├─ App.vue # 入口页面 │ ├─main.js # 源码入口 │ └─permission.js # 路由入口权限逻辑处理 ├── index.html # html模版 ├── .gitignore # 提交git需要忽略的文件 └── package.json # 依赖的包配置文件 ``` #### 1.7.2 项目启动方式 ```shell # 安装依赖 npm install # 切换淘宝源,解决 npm 下载速度慢的问题 npm install --registry=https://registry.npm.taobao.org # 启动服务 npm run ``` ### (八) Uniapp 项目目录结构 #### 1.8.1 目录结构 ```bash ├─ common # 项目源代码 │ ├─ request.js # 公共请求方法 │ ├─ util.js # 工具方法 ├─ pages # 页面目录 ├─ static # 页面目录 ├─ store # 页面目录 ├── App.vue # 入口页面 ├── main.js # 源码入口 ├── template.html # html模版 ├── .gitignore # 提交git需要忽略的文件 └── pages.json # 页面路由配置 ``` ### (九) 三方库接入规范 #### 1.HTML开发项目 引入三方JS、CSS时,禁止使用CSDN的方式,需下载到本地使用,如有min.js版本优先使用,需删除注释(含有网址、user、email等敏感信息);如没有压缩版本,可把JS源文件使用工具(https://www.jsjiami.com/jiemi.html) 进行清理注释后并使用编辑器ReformatCode #### 2.Vue和React框架项目 在Vue和react开发时,可引入插件(uglifyjs-webpack-plugin等)进行打包配置,清理掉注释和console信息,入口页面引入本地JS同HTML开发引入规则 例如: ![](https://img.kancloud.cn/a1/74/a174593dfb0045528a25dd78ad569eb6_865x455.png)