阅读 252

前端开发规范文档

没有规矩,不成方圆,对于团队来说,有一套完整的开发规范可以减少团队协作成本和维护成本,让代码阅读起来更容易。

项目结构规范

项目结构的核心思想

  • 业务功能模块的相关代码都集中在一块,方便移动和删除
  • 实现关注点分离,方便开发、调试、维护、编写、查阅、理解代码

项目目录结构

.
├── build/                      # webpack 配置文件;
│   └── ...
├── config/                     # 与项目构建相关的常用的配置选项;
│   ├── index.js                # 主配置文件
│   ├── dev.env.js              # 开发环境变量
│   ├── prod.env.js             # 生产环境变量
│   └── test.env.js             # 测试环境变量
│
├── src/
│   ├── main.js                 # webpack 的入口文件;
│   ├── assets/                 # 共用的代码以外的资源,如:图片、图标、视频 等;
│   ├── api/                    # 网络模块,如:接口;
│   ├── Router/                 # 路由模块
│   ├── I18n/                   # 国际化模块
│   ├── pages/                  # 单页页面
│   ├── vuex/                   # 组件共享状态
│   ├── common/                 # 共用的资源,如:常用的图片、图标,共用的组件、模块、样式,常量文件等等;
│   │   ├── components/         # 共用的组件,如:封装的导航条、选项卡等等; 这里的存放的组件应该都是展示组件;
│   │   ├── compatible/         # 兼容模块,如:适合App和微信各种接口的模块;
│   │   ├── extension/          # 已有类的扩展模块,如:对 Array 类型进行扩展的模块;
│   │   ├── libraries/          # 存放自己封装的或者引用的库;
│   │   ├── tools/              # 自己封装的一些工具
│   │   ├── constant.js         # 存放js的常量;
│   │   ├── constant.scss       # 存放scss的常量;
│   │   └── ...
│   └── app/                    # 存放项目业务代码;
│       ├── App.vue             # app 的根组件;
├── static/                     # 纯静态资源,该目录下的文件不会被webpack处理,该目录会被拷贝到输出目录下;
├── .babelrc                    # babel 的配置文件
├── .editorconfig               # 编辑器的配置文件;可配置如缩进、空格、制表类似的参数;
├── .eslintrc.js                # eslint 的配置文件
├── .eslintignore               # eslint 的忽略规则
├── .gitignore                  # git的忽略配置文件
├── .postcssrc.js               # postcss 的配置文件
├── CHAGNELOG.md                # 版本更新变更release
├── index.html                  # HTML模板
├── package.json                # npm包配置文件,里面定义了项目的npm脚本,依赖包等信息
└── README.md
复制代码

项目目录、组件、文档规范

目录、组件、文档命名规范

  • 能直观的感受当前目录文件的作用
  • 以小驼峰方式命名
│   ├── pages/                  # 单页页面
│   │   ├── login/              # 登录模块
│   │   │   ├── login.vue       # 登录页面
│   │   ├── userInfo/           # 用户中心模块
│   │   │   ├── center.vue      # 用户中心-主页面
│   │   │   ├── changePhone.vue # 用户中心-修改电话号码页面
复制代码

组件使用规范

  • 组件命名始终是多个单词的,避免跟元素冲突
  • 要么大写开头,要么始终用横线链接(这里项目大写开头)
  • 使用时以v-开头,多个单词用-拼接
  • 推荐使用单标签闭合
// 反例
components/
|- MyButton.vue
|- VueTable.vue
|- Icon.vue

// 好例子
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue
components/
|- AppButton.vue
|- AppTable.vue
|- AppIcon.vue
components/
|- VButton.vue
|- VTable.vue
|- VIcon.vue
复制代码
<v-ToDoSome :data="data"/>
<script>
 export default{
     components:{
         "v-ToDoSome":ToDoSome
     }
 }
</srcipt

复制代码

项目中的图片使用规范

图片命名

  • 图片文件夹不可随意命名(一般遵从页面命名,如:login/

  • 图片不可随意命名,且严禁使用0,1,等数字直接命名图片,多个单词用下划线隔开。(当前页面path+[用途]等命名,如:login_icon.png,pwd_icon.png

  • 10k以下图片建议放置assets/img下(webpack打包时直接转为base64嵌入)

  • 大图且不常更换的图片放置static/img

  • 可用css编写的样式严禁使用图片

  • 国际化图片规范,后缀使用简体-cn,英文-en,繁体-tw

│   ├── assets/               
│   │   ├── img/                          # 图片
│   │   │    ├── common/                  # 公共图片
│   │   │    │    ├── default_avatar.png  # 默认头像
│   │   │    ├── login/                   # 登录模块
│   │   │    │    ├── login1.png          # 登录模块图片
│   │   │    │    ├── login_icon-en.png      # 登录模块图片
│   │   │    │    ├── login_icon-cn.png      # 登录模块图片
│   │   │    │    ├── login_icon-tw.png      # 登录模块图片
复制代码

图片调用写法

项目下有两个文件夹放置图片地址src/assets/img,static/img

webpack打包时会直接copystatic/img下的图片,所以,当你的图片放置static/img下时,为防止图片打包重复,需要遵从以下写法:

  • static/img下的图片调用禁用require

因为通过require调用的图片会经过webpack打包,生成hash后缀,同`static/img`下图片重复

let img1 = require('../staitc/img/xxxx')//错误写法
let img2 ='../staitc/img/xxxx'//正确写法
复制代码
  • static/img下的图片不可直接嵌入img的src中

因为img标签src中的图片也会经过webpack打包

<!--错误写法-->
<img src="../static/img/xxx">
<!--正确写法-->
<img :src="`../static/img/xxx`">
复制代码
  • src/assets/img下的图片必须使用require写法,否则会报错找不到图片
<!--正确写法-->
<img src="../asset/img/xxx">
<!--错误写法-->
<img :src="`../asset/img/xxx`">
复制代码
let img1 = require('../asset/img/xxxx')//正确写法
let img2 ='../asset/img/xxxx'//错误写法
复制代码

图片写法这样区分,防止图片重复打包,增加项目体积

编码规范

html标签规范

文件编码

  • 开头声明文档类型
  • 使用语言属性
    • 中文:"zh-Hans"
    • 简体中文:"zh-cmn-Hans"
    • 繁体中文:"zh-cmn-Hant"
    • 英文:"en"
  • 使用不带BOM的UTF-8编码
  • 在HTML中指定编码<meta charset="utf-8">
  • SEO优化
  • viewport是否可缩放(为移动设备优化)
  • favicon:如果未指定,大多数浏览器会请求根目录下的favicon,为避免404错误,两种解决方法,一是在根目录放置favicon.ico文件,二是使用link指定favicon文件
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <!-- SEO -->
    <title>Style Guide</title>
    <meta name="keywords" content="your keywords">
    <meta name="description" content="your description">
    <meta name="author" content="author,email address">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="shortcut icon" href="path/to/favicon.ico">
  </head>
</html>
复制代码

外链资源URL协议

省略外链资源(图片及其它媒体资源)URL 中的 http / https 协议,使 URL 成为相对地址,避免Mixed Content 问题,减小文件字节数。

其它协议(ftp 等)的 URL 不省略。

<!-- 推荐 -->
<script src="//www.xxx.cn/statics/js/autotrack.js"></script>

<!-- 不推荐 -->
<script src="http://www.xxx.cn/statics/js/autotrack.js"></script>
复制代码
/* 推荐 */
.example {
  background: url(//www.google.com/images/example);
}

/* 不推荐 */
.example {
  background: url(http://www.google.com/images/example);
}
复制代码

Mixed Content:http和https混用造成的问题。

属性顺序

  • class(class 是最高的复用设计,应该放在最前)
  • id name(id 应尽量少用)
  • data-\\* 自定义属性(属性名称全小写用-做连接)
  • src (资源文件)
  • placeholder title alt (提示)
  • required readonly disable(辅助)

id class命名规则

  • 首先根据内容命名,如:nav,header
  • 内容中的子元素使用-链接,名称一律小写,如:card-item
  • 修饰类(易变的)使用--链接,如:card-item--warning
  • 若无内容,结合行为进行辅助,如:box-shawder
  • 不影响语义的情况下,可缩写,如:img-box,btn
  • 避免广告拦截词汇:ad,gg,banner,guagngao

语义化

语义的HTML结构,有助于机器搜索,保证代码可读性。

常见的标签语义

标签 语义
<p> 段落
<h1,2,3> 标题
<ul> 无序列表
<ol> 有序列表
<blockquote> 大段引用
<cite> 一般引用
<b> 为样式加粗
<strong> 为强调加粗
<i> 为样式倾斜
<em> 为强调倾斜
<code> 代码标识
…… ……

例如:

  • h1 大标题,一般用于banner背景,一个页面有且只有一个
  • h2 章节标题,可以有多个
  • h3 章节内的文章标题
  • h4,h5,h6 小标题/副标题
  • p 段落
├── h1---文章大标题
│   ├── h2--- 这里是一个节点
│   │   ├──h3--- 节点内的文章标题
│   │   │   ├── h4,h5,h6--- 副标题/作者等信息
│   │   │   ├── p---段落
│   ├── h2--- 这里是一个节点
│   │   ├──h3--- 节点内的文章标题
│   │   │   ├── h4,h5,h6--- 副标题/作者等信息
│   │   │   ├── p---段落    
复制代码

引号规范

  • 属性值使用双引号包裹
<div :data="data" data-src="some"></div>
复制代码

注释规范

<!-- 头部 -->
<view class="header">
  <!-- LOGO -->
  <image class="logo"></image>
  <!-- /LOGO -->
  <!-- 详情 -->
  <view class="detail"> </view>
  <!-- /详情 -->
</view>
<!-- /头部 -->
复制代码

css规范

css初始化及公用样式

/* ==========================================================================
   css 初始化
 ============================================================================ */
 
 /* margin padding 初始化为0 */
 body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend, button, input, textarea, th, td {
	margin: 0;
	padding: 0;
}

body, button, input, select, textarea {
	font: 12px/1.5tahoma, arial, \5b8b\4f53;
}

h1, h2, h3, h4, h5, h6 {	font-size: 100%;}
address, cite, dfn, em, var {	font-style: normal;}

code, kbd, pre, samp {font-family: couriernew, courier, monospace;}

small {font-size: 12px;}

ul, ol {list-style: none;}

a {text-decoration: none;}

a:hover {text-decoration: none;}

sup {vertical-align: text-top;}

sub {vertical-align: text-bottom;}

legend {color: #000;}

fieldset, img {border: 0;}

button, input, select, textarea {font-size: 100%;}

table {
	border-collapse: collapse;
	border-spacing: 0;
}

html, body {font-size: 10px !important;}
复制代码

flex布局共用样式类,字体大小样式类,margin,padding类:

/* flex布局共用样式类,字体大小样式类,margin,padding
(如有需求,可自行添加)
 ============================================================================ */
.yl-flex{
    dispaly:flex;
 }
 
.flex-center-center{
    justify-content: center;
    justify-items: center;
    align-items: center
 }
 
.flex-start-center{
    justify-content: start;
    justify-items: center;
    align-items: center
 }
 
.flex-end-center{
    justify-content: end;
    justify-items: center;
    align-items: center
 }

.flex-wrap{
  flex-wrap: wrap;
}

.flex-column{
  flex-direction:column;
}

.flex-space-around{
  justify-content: space-around;
}

/* 文本 */
.tl {text-align: left;}

.tr {	text-align: right;}

.tc {	text-align: center;}

/* 按钮 */
.btn {
    display: inline-block;
}

.btn-success {
    background: @success;
}

.btn-error {
    background: @error;
}
/* 按钮禁用 */
.disabled {
	outline: 0 none;
	cursor: default !important;
	opacity: .4;
	filter: alpha(opacity=40);
	-ms-pointer-events: none;
	pointer-events: none;
}

/* 浮动与清除浮动 */
.fl {
	float: left;
}

.fr {
	float: right;
}

.fix {
	*zoom: 1;
}

.fix:after {
	display: table;
	content: '';
	clear: both;
}

/* 显示 */ 
.dn {
	display: none;
}

.di {
	display: inline;
}

.db {
	display: block;
}

.dib {
	display: inline-block;
}

.dt {
	display: table;
}

/* 定位 */ 
.pr {
	position: relative;
}

.pa {
	position: absolute;
}

.pf {
	position: fixed;
}

.ml20 {
	margin-left: 20px;
}

.ml10 {
	margin-left: 10px;
}

.mr20 {
	margin-right: 20px;
}

.mr10 {
	margin-right: 10px;
}

.mt20 {
	margin-top: 20px;
}

.mt10 {
	margin-top: 10px;
}

.mb20 {
	margin-bottom: 20px;
}

.mb10 {
	margin-bottom:10px;
}
.ml5{
	margin-left:5px;
}
.m10{
	margin:10px;
}
.m20{
	margin:20px;
}
.p10{
	padding:10px;
}

.p20{
	padding:20px;
}
.pb20{
	padding-bottom:20px;
}
.pb10{
	padding-bottom:20px;
}
.pt20{
	padding-top:20px;
}
.pt10{
	padding-top:10px;
}
.pl20{
	padding-left:20px;
}
.pl10{
	padding-left:10px;
}
.pr20{
	padding-right:20px;
}
.pr10{
	padding-right:10px;
}
.rotate90{
	transform: rotate(90deg);
}
.rotate180{
	transform: rotate(180deg);
}
.rotate270{
	transform: rotate(270deg);
}
/* 图片居中 */
.img-middle{
	object-fit: contain;
}
/* 文本超出隐藏 */
.txt-ellipsis{
	overflow: hidden;
	text-overflow:ellipsis;
	white-space: nowrap;
}

.min-h100{
	min-height:100%;
}

.show {
	display: block;
}

.hide {
	display: none;
}

/* 字体 */

.f12 {
	font-size: 12px;
}

.f14 {
	font-size: 14px;
}

.f15 {
	font-size: 15px;
}
.f16 {
	font-size: 16px;
}

.f18 {
	font-size: 18px;
}

.f20 {
	font-size: 20px;
}

.f24 {
	font-size: 24px;
}

.f36 {
	font-size: 36px;
}
.f48 {
	font-size: 48px;
}
/* 滚动条优化 */
.scroll-style::-webkit-scrollbar {
	width: 5px;
	height: 5px;
}

.scroll-style::-webkit-scrollbar-thumb {
	border-radius: 3px;
	background: #ccc;
}

.scroll-style::-webkit-scrollbar-track {
	width: 7px;
	background: #ebebeb;
}

复制代码

属性顺序

  • 位置属性(position,top,right,z-index,display,flaot)
  • 大小(width,height,padding,margin)
  • 文字(font,line-height,letter-spacing, color)
  • 背景 (background,border)
  • 其他(animation,transition)

媒体查询

尽量将媒体查询的规则靠近与他们相关的规则,不要将他们一起放到一个独立的样式文件中,或者丢在文档的最底部,这样做只会让大家以后更容易忘记他们。

.element { ... }
.element-avatar { ... }
.element-selected { ... }

@media (max-width: 768px) {
  .element { ...}
  .element-avatar { ... }
  .element-selected { ... }
}
复制代码

属性简写

属性简写需要你非常清楚属性值的正确顺序,而且在大多数情况下并不需要设置属性简写中包含的所有值,所以建议尽量分开声明会更加清晰;


/* not good */
.element {
    transition: opacity 1s linear 2s;
}
 
/* good */
.element {
    transition-delay: 2s;
    transition-timing-function: linear;
    transition-duration: 1s;
    transition-property: opacity;
}
复制代码

margin 和 padding 相反,需要使用简写;margin 和 padding 相反,需要使用简写;

注释规范

  • 组件块和子组件之间的注释
/* ==========================================================================
   组件块
 ============================================================================ */

/* 子组件块
 ============================================================================ */
.selector {
  padding: 15px;
  margin-bottom: 15px;
}

/* 子组件块
 ============================================================================ */
.selector-secondary {
  display: block; /* 注释*/
}

.selector-three {
  display: span;
}
复制代码
  • 单行注释/*后跟空格
/* xxx */
复制代码

less规范

  • 组织顺序

    • @import
    • 变量声明
    • 样式声明
  • 避免嵌套过多,将嵌套深度限制在3级,超过需重新评估

@import "mixins/size.less";

@default-text-color: #333;

.page {
  width: 960px;
  margin: 0 auto;
}
复制代码

其他规范

  • 去掉小数点后面的0,如:rgba(0,0,0,0.5)=>rgba(0,0,0,.5)
  • 颜色代码尽量简写,如:#fff
  • 尽量少用元素选择器,元素选择器和 ID、Class 混合使用也违反关注分离原则。如果HTML标签修改了,就要再去修改 CSS 代码,不利于后期维护。
/* 不推荐 */
.red {}
.box_green {}
.page .header .login #username input {}
ul#example {}

/* 推荐 */
#nav {}
.box-video {}
#username input {}
#example {}
复制代码

js规范

缩进

html,css,js缩进一致,使用4个空格。

空格

  • 二元运算符前后
  • 三元运算符前后
  • 代码块{
  • 关键字前:else, while, catch, finally
  • 关键字后:if, else, for, while, do, switch, case, catch, finally, with, return
  • 单行注释//后,多行注释/*
  • 对象的属性值前
  • for 循环
  • 函数的参数之间
  • 运算符前后
  • 函数声明,函数表达式(前不要空格,)后空格

空行

  • 变量声明后
  • 注释前
  • 代码块后
  • 文件最后保留一个空行
let string = 'my'

let obj = {
    'name': 'yang'
}

{
    // do something
}

/* zheli */
if {
    
} else {
    
}

复制代码

引号

  • 最外层统一使用单引号。
let str = 'my name is'
复制代码

模板字符串

  • 需要拼接,尽量少用+,多使用模板字符串

let str1 = 'yang'

let string = `hello ${str1}`

复制代码

命名规范

  • 变量命名:小驼峰命名

  • 参数名:小驼峰命名

  • 函数名:小驼峰命名

  • 方法/属性名:小驼峰命名

  • 类名开头大写

  • 私有属性、变量和方法以下划线 _ 开头。

  • 常量名:全部使用大写+下划线

  • 由多个单词组成的缩写词,在命名中,根据当前命名法和出现的位置,所有字母的大小写与首字母的大小写保持一致。

  • 语义

    • 变量应当使用名词,尽量符合当时语义
    • boolean类型应当使用 is , has 等开头
    • 点击事件命名方式:tap + onClick()

let loadingModules = {};

const HTML_ENTITY = {};

function stringFormat(theBells) {}

function insertHTML(element, html) {}

function Engine(options) {}

复制代码

二元三元操作符

  • 可用于简单的if替代
  • 操作符始终写在前一行,避免产生预想不到的问题
// 不推荐 
var x = a ? b : c;

// 推荐 
var y = a ?
    longButSimpleOperandB : longButSimpleOperandC;

var z = a ?
        moreComplicatedB :
        moreComplicatedC;
复制代码

&& 和 ||

二元布尔操作符是可短路的, 只有在必要时才会计算到最后一项。

// 不推荐
function foo(opt_win) {
  var win;
  if (opt_win) {
    win = opt_win;
  } else {
    win = window;
  }
  // ...
}

if (node) {
  if (node.kids) {
    if (node.kids[index]) {
      foo(node.kids[index]);
    }
  }
}

// 推荐
function foo(opt_win) {
  var win = opt_win || window;
  // ...
}

var kid = node && node.kids && node.kids[index];
if (kid) {
  foo(kid);
}
复制代码

声明规范

  • 尽量使用 let 声明变量,少用 var 。

分号

以下情况需要加分号

  • 表达式
  • return
  • throw
  • break
  • continue
  • do-while

注释规范

  • 单行注释,独占一行,//后跟空格

  • 多行注释,/*后跟空格

  • 函数/方法注释

    • 注释必须包含函数声明,有参数和返回值时必须注释标识
    • 参数和返回类型必须包含类型信息和说明
    • 当函数是内部函数,外部不可访问时,可使用@inner标识

// 注释

/* xxxx
 xxxx
 xxxxx
/*

/** 
 * 函数描述
 * @param {string} p1 参数说明
 * @param {string} p2 参数2的说明,比较长
 *     那就换行了.
 * @param {number=} p3 参数3的说明(可选)
 * @return {Object} 返回值描述
/*
function foo(p1, p2, p3) {
    return {
        p1: p1,
        p2: p2
    }
}
复制代码

代码提交规范及版本管理

另一篇文详细解说:代码提交规范及版本管理

关注下面的标签,发现更多相似文章
评论