Skip to content

chenfahui/frontend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

前端开发规范

代码的目录结构

一般项目的目录结构如下:

./ 项目根目录
│  index.html 首页面
│  
└─assets     静态资源文件夹
    ├─css    CSS代码文件夹, 也可以放置less, sass等CSS预处理语言的代码
    │  │  
    │  └─img CSS引用的图片, 比如图标, 背景图片等
    │
    ├─img    页面直接引用的图片, 比如轮播图片
    │    
    ├─js     JS代码文件夹, 也可以放置coffeescript等js预处理语言的代码
    │      
    └─lib    第三方库的文件夹, 每一个库应单独建立一个文件夹,
                  用来放置该库的所有文件, 包括js,css,图片, 字体等
       

文件规范

编码方式

代码文件统一使用 无BOM头的utf-8(utf-8 without BOM) 的编码方式.

文件命名

文件名称以及文件后缀中的 英文字母统一使用小写 , 如 bg.png, index.html, app.js等.

文件名命名只能使用 英文字母数字 以及 - (连字符), 不要使用中文字符. 一般使用多个单词组合使用连字符连接, 单词可使用常见缩写, 不可过度缩写. 如 user-module.js, sidebar.css, i18n-tpl.html等.

文件后缀

  • HTML文件要以 .html 结尾.
  • Javascript文件以 .js 结尾
  • CSS文件以 .css 结尾

编码规范

通用规范

缩进

代码文件统一使用4个空格来作为一次缩进, 不要使用tab或者tab与空格混用, 以保证代码在不同环境下显示一致.

可在代码编辑器的配置中将一个tab的大小设置为4个空格.

注释

根据需要,在可能的情况下给代码块(或者函数)做注释:这块实现了什么功能,它的目的是什么,为什么这种方案更好?(注释代码不是强制要求,视乎项目性质和复杂程度)

待办事项

在代码的注释中使用 TODO (全大写)关键字来标识待办事项, 使用TODO(联系人) 的形式附上联系信息(姓名, 邮箱等)方便联系; 在冒号后加上待办事项内容. 在代码发布时要确认代码中无任何TODO标识.

// TODO(张工): 参数暂未校验
funtion submitOrder (data) {
    ....
}

行尾空格

删除所有的行尾空白.

HTML部分

文档类型

推荐使用HTML5文档类型 <!DOCTYPE html>

编码方式

编码方式除统一使用utf-8 without BOM之外, 在HTML的head还需要指定编码方式:

<meta charset="utf-8">

缩进

除了一个使用2个空格作为一次缩进, 在嵌套节点上也应当有缩进.

<ul>
    <li>子节点</li>
</ul>

大小写

所有代码只使用小写:包括标签、选择器、属性及属性值(文本节点例外,作为内容时例外).

<img class="avatar" src="face.png" alt="User Avatar" >

语法

  • 在属性上,使用双引号,不要使用单引号.
  • 不要在自动闭合标签结尾处使用斜线
  • 不要忽略可选的关闭标签(例如,</li></body>).

实用高于完美

尽量遵循 HTML 标准和语义,但是不应该以浪费实用性作为代价.任何时候都要用尽量小的复杂度和尽量少的标签来解决问题

减少标签数量

在编写 HTML 代码时,需要尽量避免多余的父节点.很多时候,需要通过迭代和重构来使 HTML 变得更少. 参考下面的示例:

<!-- 不推荐 -->
<span class="avatar">
    <img src="...">
</span>

<!-- 推荐 -->
<img class="avatar" src="...">

属性顺序

HTML 属性应该按照特定的顺序出现以保证易读性.

  • id
  • class
  • name
  • data-*
  • src, for, type, href
  • title, alt

Classes 是为高可复用组件设计的,理论上他们应处在第一位.Ids 更加具体而且应该尽量少使用(例如, 页内书签),所以他们处在第二位.但为了突出id的重要性, 把id放到了第一位.

Boolean 属性

不要为 Boolean 属性添加取值.

<input type="text" disabled>
<input type="checkbox" value="1" checked>
<select>
    <option value="1" selected>1</option>
</select>

引入 CSS 和 JavaScript

在引入外部 CSS 和 JavaScript 文件时不需要指明 type,因为 text/css 和 text/javascript 分别是他们的默认值.

对于比较流行的第三方库, 可以考虑使用第三方CDN(如微软,新浪等)托管的库, 以提升文件的加载速度.

CSS
  • CSS文件的引入一般放在head标签内, 以避免页面加载是出现页面闪烁的情况
  • 由团队自己开发的的CSS文件一般在第三方CSS文件之后引入, 以提升团队开发的样式的优先级, 方便修改第三方库的样式
  • 不要直接修改第三方CSS文件内的样式
  • 不要使用 style 标签去设置元素样式
  • 同时也应减少使用javascript 操作dom的style属性来修改样式, 推荐使用修改class的方式来修改样式
  • 尽量避免使用style标签来书写样式(404,500, 403等错误页面除外).

所有的样式应集中在外部的css文件中, 方便维护和管理.

Javascript
  • javascript文件的引入一般放在body结束标签之前, 避免由于javascript加载及执行时间太长导致整个页面长时间无法完成加载
  • 由团队自己开发的javascript文件一般应在第三方库之后引入, 避免团队开发 的javascript文件引入第三方库时报错
  • 不要直接修改第三方库的javascript文件.
  • 不要使用onclick, onload等以on开头的属性来给HTML元素绑定事件; 同时也应减少使用无 src属性的script标签.

所有的javascript代码应集中在js文件中, 方便维护和管理.

CSS部分

语法

  • 使用组合选择器时,保持每个独立的选择器占用一行.
  • 为了代码的易读性,在每个声明的左括号前增加一个空格.
  • 声明块的右括号应该另起一行.
  • 每条声明 : 后应该插入一个空格.
  • 每条声明应该只占用一行来保证错误报告更加准确.
  • 所有声明应该以分号结尾.虽然最后一条声明后的分号是可选的,但是如果没有他,你的代码会更容易出错.
  • 逗号分隔的取值,都应该在逗号之后增加一个空格.比如说box-shadow
  • 不要在颜色值 rgb() rgba() hsl() hsla()rect() 中增加空格,并且不要带有取值前面不必要的 0 (比如,使用 .5 替代 0.5).
  • 所有的十六进制值都应该使用小写字母,例如 #fefefe. 尽可能使用短的十六进制数值,例如使用 #fff 替代 #ffffff.
  • 为选择器中的属性取值添加引号,例如 input[type="text"]. 他们只在某些情况下可有可无,所以都使用引号可以增加一致性.
  • 不要为 0 指明单位,比如使用 margin: 0; 而不是 margin: 0px;.
/* 不推荐 */
.selector, .selector-secondary, .selector[type=text] {
    padding: 15px;
    margin: 15px;
    margin-bottom: 0px;
    background-color: rgba(0, 0, 0, 0.5);
    box-shadow: 0 1px 2px #CCC, inset 0 1px 0 #FFFFFF
}

/* 推荐 */
.selector,
.selector-secondary,
.selector[type="text"] {
    padding: 15px;
    margin: 15px;
    margin-bottom: 0;
    background-color: rgba(0,0,0,.5);
    box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
}

不要使用 @import

与 标签相比, @import 更慢, 增加了额外的页面请求,可能还会导致不可预见的问题.避免使用它们, 改用以下的方法:

  • 多用几个 标签
  • 将你的css编译到一个文件里

媒体查询位置

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

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

@media (min-width: 480px) {
    .element { ...}
    .element-avatar { ... }
    .element-selected { ... }
}

前缀属性

当使用浏览器私有前缀属性时,通过缩进使取值垂直对齐以便多行编辑, 并将标准属性放置在最后.

.selector {
    -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.15);
            box-shadow: 0 1px 2px rgba(0,0,0,.15);
}

单条声明的声明块

在一个声明块中只包含一条声明的情况下,为了易读性和快速编辑可以考虑移除其中的换行. 所有包含多条声明的声明块应该分为多行。

这样做的关键因素是错误检测. 例如, 一个 CSS 验证程序显示你在 183 行有一个语法错误,如果是一个单条声明的行,那就是他了。在多个声明的情况下,你必须为哪里出错了费下脑子。

/* 单条声明 */
.span1 { width: 60px; }
.span2 { width: 140px; }
.span3 { width: 220px; }

/* 多条声明 */
.sprite {
    display: inline-block;
    width: 16px;
    height: 15px;
    background-image: url(../img/sprite.png);
}

属性简写

坚持限制属性取值简写的使用,属性简写需要你必须显式设置所有取值。常见的属性简写滥用包括:

  • padding
  • margin
  • font
  • background
  • border
  • border-radius

大多数情况下,我们并不需要设置属性简写中包含的所有值。例如,HTML 头部只设置上下的 margin,所以如果需要,只设置这两个值。过度使用属性简写往往会导致更混乱的代码,其中包含不必要的重写和意想不到的副作用。

/* 不推荐 */
.element {
    margin: 0 0 10px;
    background: red;
    background: url("image.jpg");
    border-radius: 3px 3px 0 0;
}

/* 推荐 */
.element {
    margin-bottom: 10px;
    background-color: red;
    background-image: url("image.jpg");
    border-top-left-radius: 3px;
    border-top-right-radius: 3px;
}

class 命名

  • 保持 class 命名为全小写,可以使用连字符(不要使用下划线和 camelCase 命名)。短划线应该作为相关类的自然间断。(例如,.btn.btn-danger)。
  • 避免过度使用简写。.btn 可以很好地描述 button,但是 .s 不能代表任何元素。
  • Class 的命名应该尽量短,也要尽量明确。
  • 使用有意义的名称;使用结构化或者作用目标相关,而不是抽象的名称。
  • 命名时使用最近的父节点或者父 class 作为前缀。
  • 使用 .js-* classes 来表示行为(相对于样式, 方便js来标记元素),但是不要在 CSS文件中为其编写样式。
/* 不推荐 */
.t { ... }
.red { ... }
.header { ... }

/* 推荐 */
.tweet { ... }
.important { ... }
.tweet-header { ... }

选择器

  • 使用 classes 而不是通用元素标签来优化渲染性能。
  • 避免在经常出现的组件中使用一些属性选择器 (例如,[class^="..."])。浏览器性能会受到这些情况的影响。
  • 减少选择器的长度,每个组合选择器选择器的条目应该尽量控制在 3 个以内。
/* 不推荐 */
span { ... }
.page-container #stream .stream-item .tweet .tweet-header .username { ... }
.avatar { ... }

/* 推荐 */
.avatar { ... }
.tweet-header .username { ... }
.tweet .avatar { ... }

JAVASCRIPT部分

缩进,分号,单行长度

  • 每条语句之后一律以分号结束,不可以省略
  • 单行长度,理论上不要超过80列, 方便阅读,超过80个字符的字符串应该使用字符串连接换行
if (typeof user === "undefined" ||
    typeof user.readed === "undefined" ||
    user.readed !== true) {
    url = "http://demo.example.com/location2.js";
} else {
    url = "http://demo.example.com/location4.js";
}

大括号

和大多数语言一样 Javascript 使用大括号{} 来区分代码区块, 表示区块起始的大括号不要新起一行, 而应当放置在区块起始行的行尾.

// 不推荐
if (condition)
{
    ...
}

function foo()
{
    ...
}

// 推荐
if (condition) {
    ...
}

function foo() {
    ...
}

空格

  • 数值操作符(如, +/-/*/% 等)两边留空
  • 赋值操作符/等价判断符两边留一空格
  • js语言关键字后应有空格
  • for 循环条件中, 分号后留一空格
  • 变量声明语句, 数组值, 对象值及函数参数值中的逗号后留一空格
  • 空行不要有空格
  • 行尾不要有空格
  • 逗号和冒号后一定要跟空格
  • 点号前后不要出现空格
  • 空对象和数组不需要填入空格
  • 函数名末尾和左括号之间不要出现空格
  • 左大括号之前应该有空格
  • 使用一个 var 以及新行声明多个变量,缩进4个空格
// 不规范
foo (bar)
return(a+b);
if(a === 0) {...}
function foo (b) {...}
function(x) {...}

// 规范
function foo(num) {
    if (num < 2 ) {
        num *= 2;
    }
    return num;
}

空行

  • 方法之间加
  • 单行或多行注释前加
  • 逻辑块之间加空行增加可读性

变量命名

  • 标准变量采用驼峰标识
  • 使用的ID的地方一定全大写
  • 使用的URL的地方一定全大写
  • 涉及Android的,一律大写第一个字母
  • 涉及iOS的,一律小写第一个,大写后两个字母
  • 常量采用大写字母,下划线连接的方式
  • 构造函数,大写第一个字母
var thisIsMyName;

var goodID;

var reportURL;

var AndroidVersion;

var iOSVersion;

var MAX_COUNT = 10;

function Person(name) {
    this.name = name
}

字符常量

一般情况下统一使用 '' 单引号

var name = 'Judy';

null的使用场景

  • 初始化一个将来可能被声明为一个对象的变量
  • 与一个可能是对象或者非对象的初始化变量相比
  • 传入一个对象待定的函数
  • 作为一个对象待定的函数的返回值

不适合null的使用场景

  • 不要使用null来测试一个一个变量是否存在
  • 不要用null来测试一个没声明的变量

undefined使用场景

一个只声明未定义的变量其值即为undefined, 不要给一个刚声明的变量赋值为undefined.

永远不要直接使用undefined进行变量判断, 使用字符串 "undefined" 对变量进行判断.

// 不推荐
var person;
console.log(person === undefined);    //true

// 推荐
console.log(typeof person);    // "undefined"

字面量

使用字面量的方式来定义javascript内置类型的变量, 不要使用new操作符. 使用字面量更容易阅读, 而且不会出现潜在错误.

// 对象的字面量
// 不推荐
var team = new Team();
team.title = "AlloyTeam";
team.count = 25;
// 推荐
var team = {
    title: "AlloyTeam",
    count: 25
};

// 数组的字面量
// 不推荐
var colors = new Array("red", "green", "blue");
var numbers = new Array(1, 2, 3, 4);
// 推荐
var colors = [ "red", "green", "blue" ];
var numbers = [ 1, 2, 3, 4 ];

// 正则字面量
// 不推荐
var reg = new RegExp('\s+',g);
// 推荐
var reg = /\s+/g;

// 字符串字面量
// 不推荐
var str = new String('Hello');
// 推荐
var str = 'Hello';

// 数字字面量
// 不推荐
var num = new Number(12);
// 推荐
var num = 12;

// 布尔字面量
// 不推荐
var isLoaded = new Boolean(false);
// 以下语句会弹出对话框 Yes
if (isLoaded) {
    alert('Yes');
}
// 推荐
var isLoaded = false;
// 以下语句中的alert则不会执行
if (isLoaded) {
    alert('Yes');
}

this 的引用

  • 当保存对 this 的引用时使用 _this.
// 不推荐
function() {
  var self = this;
  return function() {
    console.log(self);
  };
}

// 不推荐
function() {
  var that = this;
  return function() {
    console.log(that);
  };
}

// 推荐
function() {
  var _this = this;
  return function() {
    console.log(_this);
  };
}

switch...case结构

switch...case结构要求,在每一个case的最后一行必须是break语句,否则会接着运行下一个case。这样不仅容易忘记,还会造成代码的冗长。

而且,switch...case不使用大括号,不利于代码形式的统一。此外,这种结构类似于goto语句,容易造成程序流程的混乱,使得代码结构混乱不堪,不符合面向对象编程的原则。

function doAction(action) {
  switch (action) {
    case 'hack':
      return 'hack';
    break;

    case 'slash':
      return 'slash';
    break;

    case 'run':
      return 'run';
    break;

    default:
      throw new Error('Invalid action.');
    break;
  }
}

// 建议用对象结构代替
function doAction(action) {
  var actions = {
    'hack': function () {
      return 'hack';
    },

    'slash': function () {
      return 'slash';
    },

    'run': function () {
      return 'run';
    }
  };
 
  if (typeof actions[action] !== 'function') {
    throw new Error('Invalid action.');
  }

  return actions[action]();
}

条件表达式和等号

  • 适当使用 ===!== 以及 ==!=.
  • 条件表达式的强制类型转换遵循以下规则:
    • 对象 被计算为 true
    • Undefined 被计算为 false
    • Null 被计算为 false
    • 布尔值 被计算为 布尔的值
    • 数字 如果是 +0, -0, or NaN 被计算为 false , 否则为 true
    • 字符串 如果是空字符串 '' 则被计算为 false, 否则为 true
if ([0]) {
  // true
  // An array is an object, objects evaluate to true
}
  • 使用快捷方式
// 不推荐
if (name !== '') {
  // ...stuff...
}

// 推荐
if (name) {
  // ...stuff...
}

// 不推荐
if (collection.length > 0) {
  // ...stuff...
}

// 推荐
if (collection.length) {
  // ...stuff...
}

在做长方法链时使用缩进.

// 不推荐
$('#items').find('.selected').highlight().end().find('.open').updateCount();

// 推荐
$('#items')
  .find('.selected')
    .highlight()
    .end()
  .find('.open')
    .updateCount();

// 不推荐
var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true)
    .attr('width',  (radius + margin) * 2).append('svg:g')
    .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
    .call(tron.led);

// 推荐
var leds = stage.selectAll('.led')
    .data(data)
  .enter().append('svg:svg')
    .class('led', true)
    .attr('width',  (radius + margin) * 2)
  .append('svg:g')
    .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
    .call(tron.led);

单行注释

  • 双斜线后,必须跟注释内容保留一个空格
  • 可独占一行, 前边不许有空行, 缩进与下一行代码保持一致
  • 可位于一个代码行的末尾,注意这里的格式
// 推荐
if (condition) {

    // 通过安全检查
    allowed();
}

var zhangsan = "zhangsan";    // 双斜线距离分号一个缩进, 双斜线后保留一个空格

多行注释

  • 最少三行, 格式如下
  • 前边留空一行
/*
 * 注释内容与星标前保留一个空格
 */
何时使用
  • 难于理解的代码段
  • 可能存在错误的代码段
  • 浏览器特殊的HACK代码
  • 业务逻辑强相关的代码

文档注释

对于函数以及全局变量, 需要有详细的文档注释. 文档注释是使用@param @return等标签来注解, 请参考 http://usejsdoc.org/

函数注释格式如下

/**
 * 函数功能描述
 * @param  {参数类型}   参数名      参数描述
 * @return {返回数据类型}           返回数据描述
 */

// 例如
/**
 * 判断参数是否为数字
 * @param  {Number}   num   待判断的参数, 可以是任意类型
 * @return {Boolean}        若参数为数字则返回true, 否则false
 */
function isNum(num) {
    return !isNaN(num);
}

全局变量注释格式如下

/**
 * 常量描述
 * @type {常量类型}
 */

// 例如
/**
 * 每页请求的数据条数
 * @type {Number}
 */
var PAGE_SIZE = 10;

其他

尽量避免使用 == !=, 推荐使用严格比较 === !== .

  • eval 非特殊业务, 禁止使用
  • with 非特殊业务, 禁止使用

About

Front-end development specification

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published