前言
不管参与项目的人数有多少,确保每一行代码都像是同一个人编写的;
规范的代码可以更易于阅读与维护,对长期项目大有裨益;
实施代码规范减少低级 bug 的出现概率;
实施代码规范增加代码可读性,提高协作开发效率;
提供相关工具(插件),保障代码规范的无缝接入。
编辑器设置
代码编辑器的设置 将编辑器 按照下面的配置进行设置 以避免常见的代码不一致的差异
用两个空格代替制表符 文档设置为utf-8 在文件结尾添加 一个空白行
二、文件/文件夹/资源命名
在 web 项目中,所有的文件名应该都遵循同一命名约定。以可读性而言,减号(-)是用来分隔文件名的不二之选。同时它也是常见的 URL 分隔符(i.e. //example.com/blog/my-blog-entry or //s.example.com/images/big-black-background.jpg),所以理所当然的,减号应该也是用来分隔资源名称的好选择。
请确保文件命名总是以字母开头而不是数字。而以特殊字符开头命名的文件,一般都有特殊的含义与用处(比如 compass[1] 中的下划线就是用来标记跳过直接编译的文件用的)。
资源的字母名称必须全为小写,这是因为在某些对大小写字母敏感的操作系统中,当文件通过工具压缩混淆后,或者人为修改过后,大小写不同而导致引用文件不同的错误,很难被发现。
还有一些情况下,需要对文件增加前后缀或特定的扩展名(比如 .min.js, .min.css),抑或一串前缀(比如 3fa89b.main.min.css)。这种情况下,建议使用点分隔符来区分这些在文件名中带有清晰意义的元数据。
大多 Web 服务器 (Apache, Unix) 对大小写敏感: london.jpg 不能通过 London.jpg 访问。
其他 Web 服务器 (Microsoft, IIS) 对大小写不敏感: london.jpg 可以通过 London.jpg 或 london.jpg 访问。
你必须保持统一的风格,我们建议统一使用小写的文件名。
1、文件夹
全部使用小写字母组成,由字母和数字中滑线组成。(box, cell-box , cell-form-preview)。
2、文件
推荐
my-script.js
my-css.css
my-html.html
my-main.min.js
my-reset.min.css
不推荐
myScript.js
myCss.css
myHtml.html
3、图片命名
参照文件命名通用规则
- 图标类图片,需在文件名前面加上 ico_ 前缀。
- 背景类图片,需在文件名前面加上 bg_ 前缀。
- 雪碧图图片,需在文件名后面加上 _sprite 后缀。
- Retina 图片,需在文件名后面加上 _1x 或 _2x 后缀来标记原图和 2 倍图。
三、HTML编码规范
结构、表现、行为三者分离。
尽量在文档和模板中只包含结构性的 HTML;而将所有表现代码,移入样式表中;将所有动作行为,移入脚本之中。
在此之外,为使得它们之间的联系尽可能的小,在文档和模板中也尽量少地引入样式和脚本文件。
建议:
HTML只关注内容
HTML只显示展示内容信息
不要引入一些特定的 HTML 结构来解决一些视觉设计问题
不要将img元素当做专门用来做视觉设计的元素
样式上的问题应该使用css解决
1、基本规则
- css 引用置于头部标签内。
- js 引用置于底部标签前。(部分场景除外,例如:计算font-size大小的代码)
- 不要使用 HTML5 规范中已经被废弃的标签(具体废弃的标签请自行查阅文档);
- 使用 label 包裹附加文字的表单输入框(radio、checkbox);
- 属性名全小写,多个单词用中划线做分隔符;
- 属性值使用双引号,不要使用单引号;
- 每个块级、列表、表格元素单独占一行,每个子元素都相对父元素缩进,缩进使用 2空格;
<!DOCTYPE html>
<html>
<head>
<title>载入中</title>
</head>
<body>
<!-- 属性名全小写,多个单词用中划线做分隔符;
属性值使用双引号,不要使用单引号; -->
<div class="my-style" id="app"></div>
</body>
</html>
2、文档头
推荐使用 HTML5 的文档类型申明:
页面开头必须有文档头声明,推荐使用 HTML5 简单的 doctype 声明来启用标准模式,使页面在每个浏览器中尽可能一致的展现。
按照惯例,doctype 应大写。
示例:
<!DOCTYPE html>
<html>
...
</html>
3、html要加上lang的属性
html根元素指定lang属性,从而为文档设置正确的语言。
如下,如果是英文的网页,应该这么写:
<!DOCTYPE html>
<html lang="zh-CN">
<!--
1、lang="en"
2、lang="en-US"
第一种表示它是英文的网页,第二种表示它是美国英语的网页,加上这个的好处是有利于SEO和屏幕阅读器使用者,他可以快速地知道这个网页是什么语言的,如果是中文可以这么写:
-->
4、声明文档的编码charset,且与文件本身编码保持一致,推荐使用UTF-8编码。
一个原因是避免网页显示unicode符号时乱码,写在前面是因为w3c有规定,语言编码要在html文档的前1024个字节。如果不写的话在老的浏览器会有utf-7攻击的隐患,具体可以自行查阅资料,只是现在的浏览器基本都去掉了对utf-7编码的支持了。
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- charset的标签写成html5的这种比较简洁的写法就行了,不需要写成html4这种长长的: -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
</html>
5、每个页面必须有且仅有一个title元素
如果是单页面推荐使用默认title为载入中 或者 loading。
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>载入中</title>
</head>
</html>
6、属性顺序
HTML 属性应当按照特定的顺序依次排列,确保代码的易读性和可维护性。
Class 用于标识高度可复用组件,因此应该排在首位;id 用于标识具体组件,排在第二位。
claas
id
name
data-*
src, for,type,href,value,max-length,max,min,pattern
placeholder,title,alt
aria-*,role
required,readonly,disabled
7、BOOLEAN 属性
HTML5 规范中,boolean 属性不需要声明属性值。
Boolean 属性的存在表示取值为 true,不存在则表示取值为 false。
<!-- good -->
<input type="text" disabled>
<input type="checkbox" checked>
<!-- bad -->
<input type="text" disabled="true">
<input type="checkbox" checked="checked">
8、常用html模版
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<!-- IE 支持通过特定的<meta>标签来确定绘制当前页面所应该采用的IE版本。除非有强烈的特殊需求,否则最好是设置为edge mode,从而通知 IE 采用其所支持的最新的模式。 -->
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta name="referrer" content="always">
<!-- 移动端视口设置 -->
<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, initial-scale=1.0, minimum-scale=1.0 maximum-scale=1.0">
<title>载入中</title>
</head>
<body>
<div id="app"></div>
</body>
<script><script>
</html>
9、脚本加载
出于性能考虑,脚本异步加载很关键。一段脚本放置在 内,比如 ,其加载会一直阻塞 DOM 解析,直至它完全地加载和执行完毕。这会造成页面显示的延迟。特别是一些重量级的脚本,对用户体验来说那真是一个巨大的影响。
异步加载脚本可缓解这种性能影响。如果只需兼容 IE10+,可将 HTML5 的 async 属性加至脚本中,它可防止阻塞 DOM 的解析,甚至你可以将脚本引用写在 里也没有影响。
如需兼容老旧的浏览器,实践表明可使用用来动态注入脚本的脚本加载器。你可以考虑 yepnope 或 labjs。注入脚本的一个问题是:一直要等到 CSS 对象文档已就绪,它们才开始加载(短暂地在 CSS 加载完毕之后),这就对需要及时触发的 JS 造成了一定的延迟,这多多少少也影响了用户体验吧。
终上所述,兼容老旧浏览器(IE9-)时,应该遵循以下最佳实践。
脚本引用写在 body 结束标签之前,并带上 async 属性。这虽然在老旧浏览器中不会异步加载脚本,但它只阻塞了 body 结束标签之前的 DOM 解析,这就大大降低了其阻塞影响。而在现代浏览器中,脚本将在 DOM 解析器发现 body 尾部的 script 标签才进行加载,此时加载属于异步加载,不会阻塞 CSSOM(但其执行仍发生在 CSSOM 之后)。
所有浏览器中,推荐
<html>
<head>
<link rel="stylesheet" href="my.css">
</head>
<body>
<!-- body goes here -->
<script src="my.js" async></script>
</body>
</html>
只在现代浏览器中,推荐
<html>
<head>
<link rel="stylesheet" href="my.css">
<script src="my.js" async></script>
</head>
<body>
<!-- body goes here -->
</body>
</html>
10、特殊符号使用html实体
不要直接把Unicode的特殊符号直接拷到html文档里面,要使用它对应的实体Entity,常用的如下表所示:
符号 | 实体编码 |
---|---|
© | © |
¥ | ¥ |
® | ® |
> | > |
< | < |
& | & |
特别是像©这种符号,不要从UI里面直接拷一个unicode的字符过去,如果直接拷过去会比较丑,它取的是用的字体里面的符号。
11、标签语义化
根据元素(有时被错误地称作“标签”)其被创造出来时的初始意义来使用它。打个比方,用 heading 元素来定义头部标题,p 元素来定义文字段落,用 a 元素来定义链接锚点,等等。
有根据有目的地使用 HTML 元素,对于可访问性、代码重用、代码效率来说意义重大。
12、注释规范
页面中使用注释划分结构块,注意与css中的注释达成统一格式。
<!-- 头部 -->
<div class="g-hd">
<!-- LOGO -->
<h1 class="m-logo"><a hred="#">LOGO</a></h1>
<!-- /LOGO -->
<!-- 导航 -->
<ul class="m-nav">
<li><a hred="#">NAV1</a></li>
<li><a hred="#">NAV2</a></li>
</ul>
<!-- /导航 -->
</div>
<!-- /头部 -->
<style>
/* 头部 */
.g-hd{
display:block
}
/* /头部 */
</style>
12、id/class命名规则
遵循“内容优先,表现为辅”的基本原则
首先根据内容命名,如header、footer。若根据内容无法找到合适的命名,再结合表现进行辅助,如col-main、blue-box。
一律小写,多个单词以“-”连接
不能使用下划线和驼峰命名法,如main-nav。可基于最近的父元素名称作为前缀。
在不影响语义的情况下,可适当使用缩写
缩写只用来表示结构,如col、nav、btn等,不可自造缩写。
避免广告拦截词汇
ad、ads、adv、banner、sponsor、gg、guangg、guanggao等,页面中尽量避免采用以上词汇来命名
13、img标签要写alt属性
根据W3C标准,img标签要写alt属性,如果没有就写一个空的。但是一般要写一个有内容的,根据图片想要表达的意思,因为alt是在图片无法加载时显示的文字。有些人偷懒就直接写个空的alt那也可以,但是在一些重要的地方还是要写一下,毕竟它还是有利于SEO.如下不太好的写法:
<img src="company-logo.svg" alt="ABC Company">
14、单标签不要写闭合标签
为什么?因为写了也没用,还显得你不懂html规范,我们不是写XHTML。如果你用React写jsx模板,它就要求每个标签都要闭合,但是它始终不是原生html.常见的单标签有img、link、input、hr、br,如下好的写法:
<img src="test.jpg"><br>
<input type="email" value="">
15、自定义属性要以data-开头
自己添加的非标准的属性要以data-开头,否则w3c validator会认为是不规范的,如下不好的写法:
<!-- good -->
<div data-count="5"></div>
<!-- bad -->
<div count="5"></div>
16、ul/ol的直接子元素只能是li
有时候可能会直接在ul里面写一个div或者span,以为这样没关系:
<ol>
<span>123</span>
<li>a</li>
<li>b</li>
</ol>
这样写也是不规范的,不能直接在ol里面写span,ol是一个列表,它的子元素应该都是display: list-item的,突然冒出来个span,你让浏览器如何自处。所以写得不规范就会导致在不同的浏览器会有不同的表现。
同样,tr的直接子元素都应该是td,你在td里面写tr那就乱了。
17、行内元素里面不可使用块级元素
a标签是一个行内元素,行内元素里面套了一个div的标签,这样可能会导致a标签无法正常点击。再或者是span里面套了div,这种情况下需要把inline元素显式地设置display为block,如下代码:
<!-- good -->
<a href="/listing?id=123" style="display: block">
<div></div>
</a>
<!-- bad -->
<a href="/listing?id=123">
<div></div>
</a>
四、css常用规则
通用规则
- 元素选择器用小写字母;
- 元素选择器用小写字母;
- 不要在一个文件里出现两个相同的规则;
- 不允许驼峰命名多个字母用短杠分割;
- 每个属性声明末尾都要加分号;
缩进
与 HTML 缩进方式一样,缩进使用2 个空格宽度;
css属性声明顺序
推荐的样式编写顺序依次为:
- Positioning(定位)
- Box model(盒模型)
- Typographic(排版)
- Visual(视觉)
- Misc(杂项)
两段规则使用空一行
.demo1{
display:block;
background-color:red;
}
/* 这里空行 */
.demo1{
display:block;
background-color:red;
}
/* 只有一行规则不换行 */
.demo3 {display: inline-block;}
五、 js编码规范
1、严格模式
ECMAScript 5 严格模式可在整个脚本或独个方法内被激活。它对应不同的 javascript 语境会做更加严格的错误检查。严格模式也确保了 javascript 代码更加的健壮,运行的也更加快速。
严格模式会阻止使用在未来很可能被引入的预留关键字。
你应该在你的脚本中启用严格模式,最好是在独立的 IIFE 中应用它。避免在你的脚本第一行使用它而导致你的所有脚本都启动了严格模式,这有可能会引发一些第三方类库的问题。
2、基本通用规则
- 二元运算符两侧必须有一个空格,一元运算符与操作对象之间不允许有空格。
- 每条语句必须有结束符号 ‘;’。
- 统一使用 2 个空格做为一个缩进层级。
示例:
// 推荐
var num = 1;
var num2 = num + 3;
num++;
// 不推荐
var num=1;
var num =1;
// 代码缩进
var getName = function(name) {
if (name) {
console.log(name)
}
}
3、变量命名规则
基本规则
- 标准变量采用驼峰式命名
- ID在变量名中全大写
- URL在变量名中全大写
- Android在变量名中大写第一个字母
- iOS在变量名中小写第一个,大写后两个字母
- 常量全大写,用下划线连接
- 构造函数,大写第一个字母
- jquery对象必须以$开头命名
var thisIsMyName;
var goodID;
var reportURL;
var AndroidVersion;
var iOSVersion;
var MAX_COUNT = 10;
function Person(name) {
this.name = name;
}
// not good
var body = $('body');
// good
var $body = $('body');
4、前缀规范
解释:声明变量增加类型前缀可以帮助我们知道变量的类型,增加可读性,有益长期维护。
s:表示字符串。例如:sName,sHtml;
n:表示数字。例如:nPage,nTotal;
b:表示逻辑。例如:bChecked,bHasLogin;
a:表示数组。例如:aList,aGroup;
r:表示正则表达式。例如:rDomain,rEmail;
f:表示函数。例如:fGetHtml,fInit;
o:表示以上未涉及到的其他对象,例如:oButton,oDate;
例外情况:
1:作用域不大临时变量可以简写,比如:str,num,bol,obj,fun,arr。
2:循环变量可以简写,比如:i,j,k等。
5、声明变量必须使用关键字定义
解释:
不通过 var,let, const 等关键字定义变量将导致变量污染全局环境。
示例
// good
var name = 'xs'
// bad
name = 'xs'
6、每个 var 、let、const 只能声明一个变量。
// good
var name = 'xiaoming';
var age = 12;
let sex = '男';
let address = '上海'
const API_HOST = 'http://www.baidu.com';
const ENV = 'UAT';
// bad
var name = 'xiaoming',
age = 12;
let sex = '男',
address = '上海'
const API_HOST = 'http://www.baidu.com', ENV = 'UAT';
7、常量全部使用大些,多个单词使用 ‘_’连接。
例如:
// 推荐
const API_HOST = 'http://www.baidu.com';
8、变量命名 ,使用小驼峰命名方式
例如:
// 推荐
var myName = 'xiaoming';
9、boolean 类型的变量使用 is 或 has 开头。
例如:
var isReady = false;
var hasMoreCommands = false;
10、函数/方法命名, 使用小驼峰命名方式。函数名 使用 动宾短语
例如:
function getValue(value) {
}
// 函数参数一使用使用小驼峰命名方式。‘userName’。
function getValue(userName) {
}
11、构造函数
在JS中,构造函数也属于函数的一种,只不过采用new 运算符创建对象。
构造函数使用大驼峰(Pascal)命名法,首字母大写,类名使用名词。
构造函数内分为两种变量
1、私有属性和方法:前缀为_(下划线),后面跟公共属性和方法一样的命名方式。
2、公共属性和方法:跟变量和函数的命名一样。
例如:
function Student(name) {
var _name = name; // 私有成员
// 公共方法
this.getName = function () {
return _name;
}
// 公共方式
this.setName = function (value) {
_name = value;
}
}
var st = new Student('tom');
st.setName('jerry');
console.log(st.getName()); // => jerry:输出_name私有变量的值
12、枚举变量 使用 Pascal命名法,枚举的属性 使用 全部字母大写,单词间下划线分隔 的命名方式。
示例:
var TargetState = {
READING: 1,
READED: 2,
APPLIED: 3,
READY: 4
};
13、由多个单词组成的缩写词,在命名中,根据当前命名法和出现的位置,所有字母的大小写与首字母的大小写保持一致。
示例:
function XMLParser() {
}
function insertHTML(element, html) {
}
var httpRequest = new HTTPRequest();
14、Promise对象 用 动宾短语的进行时 表达。
示例:
var loadingData = ajax.get('url');
loadingData.then(callback);
15、常用语句流程控制和代码块格式。
then换行缩进
axios.get()
.then(() => {
// todo
})
.catch(() => {
//todo
})
if / else / for / while / function / switch / do / try / catch / finally 关键字后,必须有一个空格。
switch () {
case '1':
// todo
break;
case '2':
// todo
break;
default:
// todo
}
if (x) {
console.log(1)
} else {
console.log(2)
}
for () {
}
while () {
}
do {
} while () {
}
try {
delete obj.name;
} catch (err) {
obj.name = null;
} finally {
// finallyCode - 无论 try / catch 结果如何都会执行的代码块
}
function setValue() {
// todo
}
(function () {
// todo
})();
if else 语句只有一句时也不要省略{}
示例:
// good
if (true) {
console.log(1)
} else {
else console.log(2)
}
// bad
if (x) console.log(1)
else console.log(2)
16、在对象创建时,属性中的 : 之后必须有空格,: 之前不允许有空格。
// good
var obj = {
a: 1,
b: 2,
c: 3
};
// bad
var obj = {
a : 1,
b:2,
c :3
};
17、函数声明、具名函数表达式、函数调用中,函数名和 ( 之间不允许有空格。
// good
function funcName() {
}
var funcName = function funcName() {
};
funcName();
// bad
function funcName () {
}
var funcName = function funcName () {
};
funcName ();
18、, 和 ; 前不允许有空格。如果不位于行尾,, 和 ; 后必须跟一个空格。
// good
import {getName, b, c} from '';
getName(a, b);
// bad
getName(a , b);
19、单行声明的数组与对象,如果包含元素,{} 和 [] 内紧贴括号部分不允许包含空格。
解释:
声明包含元素的数组与对象,只有当内部元素的形式较为简单时,才允许写在一行。元素复杂的情况,还是应该换行书写。
// good
var arr1 = [];
var arr2 = [1, 2, 3];
var obj1 = {};
var obj2 = {name: 'obj'};
var obj3 = {
name: 'obj',
age: 20,
sex: 1
};
// bad
var arr1 = [ ];
var arr2 = [ 1, 2, 3 ];
var obj1 = { };
var obj2 = { name: 'obj' };
var obj3 = {name: 'obj', age: 20, sex: 1};
20、表达式
在 Equality Expression 中使用类型严格的 ===。仅当判断 null 或 undefined 时,允许使用 == null。
解释
使用 === 可以避免等于判断中隐式的类型转换。
示例:
// good
if (age === 30) {
// ......
}
// bad
if (age == 30) {
// ......
}
21、注释
单行注释
必须独占一行。// 后跟一个空格,缩进与下一行被注释说明的代码一致。
// 获取数据(说明和//之前又个空格)
function getDate() {
// todo
}
多行注释
避免使用 /…/ 这样的多行注释。有多行注释内容时,使用多个单行注释。
文档化注释
为了便于代码阅读和自文档化,以下内容必须包含以 /**…*/ 形式的块注释中。文档注释前必须空一行。
文件顶部必须包含文件注释,用 @file 标识文件说明 @Author 开发者 ,@Date 文件开发时间。
示例:
/**
* @File Describe the file
* @Author xxx
* @Date 2019-01-02
*/
解释:
开发者信息能够体现开发人员对文件的贡献,并且能够让遇到问题或希望了解相关信息的人找到维护人。通常情况文件在被创建时标识的是创建者。随着项目的进展,越来越多的人加入,参与这个文件的开发,新的作者应该被加入 @author 标识。
@author 标识具有多人时,原则是按照 责任 进行排序。通常的说就是如果有问题,就是找第一个人应该比找第二个人有效。比如文件的创建者由于各种原因,模块移交给了其他人或其他团队,后来因为新增需求,其他人在新增代码时,添加 @author 标识应该把自己的名字添加在创建人的前面。
@author 中的名字不允许被删除。任何劳动成果都应该被尊重。
业务项目中,一个文件可能被多人频繁修改,并且每个人的维护时间都可能不会很长,不建议为文件增加 @author 标识。通过版本控制系统追踪变更,按业务逻辑单元确定模块的维护责任人,通过文档与wiki跟踪和查询,是更好的责任管理方式。
对于业务逻辑无关的技术型基础项目,特别是开源的公共项目,应使用 @author 标识。
示例:
/**
* @file Describe the file
* @author author-name(mail-name@domain.com)
* author-name2(mail-name2@domain.com)
*/
函数/方法注释
函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识。
解释:
当 return 关键字仅作退出函数/方法使用时,无须对返回值作注释标识。
[强制] 参数和返回值注释必须包含类型信息,且不允许省略参数的说明。
[建议] 当函数是内部函数,外部不可访问时,可以使用 @inner 标识。
示例:
/**
* 函数描述
*
* @param {string} p1 参数1的说明
* @param {string} p2 参数2的说明,比较长
* 那就换行了.
* @param {number=} p3 参数3的说明(可选)
* @return {Object} 返回值描述
*/
function foo(p1, p2, p3) {
var p3 = p3 || 10;
return {
p1: p1,
p2: p2,
p3: p3
};
}
类型转换
转换成 string 时,使用 + ‘’。
示例:
// good
num + '';
// bad
new String(num);
num.toString();
String(num);
转换成 number 时,通常使用 +
示例:
// good
+str;
// bad
Number(str);
string 转换成 number,要转换的字符串结尾包含非数字并期望忽略时,使用 parseInt,使用 parseInt 时,必须指定进制。
示例:
good
var width = '200px';
parseInt(width, 10); // =>200
bad
parseInt(width);
转换成 boolean 时,使用 !!。
示例:
var num = 3.14;
!!num;
number 去除小数点,使用 Math.floor / Math.round / Math.ceil,不使用 parseInt。
Math.floor 向下取整
Math.round 四舍五入
Math.ceil 向上取整
示例:
// good
var num = 3.14;
Math.ceil(num);
// bad
var num = 3.14;
parseInt(num, 10);
字符串
字符串使用单引号‘string’ 不要使用 “string”,html中的属性值使用的是双引号。
解释:
- 输入单引号不需要按住 shift,方便输入。
- 实际使用中,字符串经常用来拼接 HTML。为方便 HTML 中包含双引号而不需要转义写法。
var str = '我是一个字符串';
var html = '<div class="cls">拼接HTML可以省去双引号转义</div>';
使用``做字符串拼接(es6)
示例:
// good
var host = 'www.baidu.com';
var str = `https://${host}/api`;
// bad
var host = 'www.baidu.com';
var str = 'https://' + host + '/api';
使用 数组 或 + 拼接字符串。
解释:
使用 + 拼接字符串,如果拼接的全部是 StringLiteral,压缩工具可以对其进行自动合并的优化。所以,静态字符串建议使用 + 拼接。
在现代浏览器下,使用 + 拼接字符串,性能较数组的方式要高。
如需要兼顾老旧浏览器,应尽量使用数组拼接字符串。
// 使用数组拼接字符串
var str = [
// 推荐换行开始并缩进开始第一个字符串, 对齐代码, 方便阅读.
'<ul>',
'<li>第一项</li>',
'<li>第二项</li>',
'</ul>'
].join('');
// 使用 `+` 拼接字符串
var str2 = '' // 建议第一个为空字符串, 第二个换行开始并缩进开始, 对齐代码, 方便阅读
+ '<ul>',
+ '<li>第一项</li>',
+ '<li>第二项</li>',
+ '</ul>';
Vue项目规范
https://cn.vuejs.org/v2/style-guide/
组件名为多个单词
组件名应该始终是多个单词的,根组件 App 除外。
这样做可以避免跟现有的以及未来的 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的。
// 推荐
Vue.component('todo-item', {
// ...
})
export default {
name: 'TodoItem',
// ...
}
// 不推荐
Vue.component('todo', {
// ...
})
export default {
name: 'Todo',
// ...
}
基础组件名
应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如 Base、App 或 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
组件的 data 必须是一个函数
当在组件中使用 data 属性的时候 (除了 new Vue 外的任何地方),它的值必须是返回一个对象的函数。
// good
Vue.component('some-comp', {
data: function () {
return {
foo: 'bar'
}
}
})
// In a .vue file
export default {
data () {
return {
foo: 'bar'
}
}
}
// 在一个 Vue 的根实例上直接使用对象是可以的,
// 因为只存在一个这样的实例。
new Vue({
data: {
foo: 'bar'
}
})
// bad
Vue.component('some-comp', {
data: {
foo: 'bar'
}
})
export default {
data: {
foo: 'bar'
}
}
Prop 定义应该尽量详细。
// good
props: {
status: String
}
// 更好的做法!
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
// bad
这样做只有开发原型系统时可以接受
props: ['status']
总是用 key 配合 v-for。
// good
<ul>
<li
v-for="todo in todos"
:key="todo.id"
>
{{ todo.text }}
</li>
</ul>
// bad
<ul>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ul>
私有属性名
在插件、混入等扩展中始终为自定义的私有属性使用 $_ 前缀。并附带一个命名空间以回避和其它作者的冲突 (比如 $yourPluginName)。
// good
var myGreatMixin = {
// ...
methods: {
$_myGreatMixin_update: function () {
// ...
}
}
}
// bad
var myGreatMixin = {
// ...
methods: {
update: function () {
// ...
}
}
}
var myGreatMixin = {
// ...
methods: {
_update: function () {
// ...
}
}
}
var myGreatMixin = {
// ...
methods: {
$update: function () {
// ...
}
}
}
var myGreatMixin = {
// ...
methods: {
$_update: function () {
// ...
}
}
}
组件/实例的选项的顺序
组件/实例的选项应该有统一的顺序。
这是我们推荐的组件选项默认顺序。它们被划分为几大类,所以你也能知道从插件里添加的新属性应该放到哪里。
1、副作用 (触发组件外的影响)
el
2、全局感知 (要求组件以外的知识)
- name
- parent
3、组件类型 (更改组件的类型)
- functional
4、模板修改器 (改变模板的编译方式)
-
delimiters
-
comments
5、模板依赖 (模板内使用的资源)
- components
- directives
- filters
6、组合 (向选项里合并属性)
- extends
- mixins
7、接口 (组件的接口)
- inheritAttrs
- model
- props/propsData
8、本地状态 (本地的响应式属性)
- data
- computed
9事件 (通过响应式事件触发的回调)
- watch
10、生命周期钩子 (按照它们被调用的顺序)
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- activated
- deactivated
- beforeDestroy
- destroyed
11、非响应式的属性 (不依赖响应系统的实例属性)
- methods
12、渲染 (组件输出的声明式描述)
- template/render
- renderError
常用模版
<template>
<div>
<!-- 列表渲染 保持列表渲染中每项都有key -->
<div v-for='item in todolist' :key='item.id'></div>
<!-- 自定义组件的使用 -->
<my-input></my-input>
<!-- 不要使用这种方式 -->
<MyInput></MyInput>
</div>
</template>
<script>
import { MyInput } from './components'
// 不同内容空一行
export default {
// 全局感知
name: 'WForms', // 自定义组件名称使用单词大写开头 (PascalCase)
// 模板依赖
components: {
MyInput
},
directives: {},
filters: {},
// 组合
extends: {},
mixins: [formMixin],
// 接口
props: {
value:{
required: false,
default:"",
},
title:{
required:false,
default:"标题"
},
type:{
required:false,
default:"text"
},
name:{
required:false,
default:"name"
}
},
// 本地状态 (本地的响应式属性)
data(){
return {
currentValue: this.value,
isFoucs: false
}
},
computed: {
// todo
},
// 事件
watch:{
value (newVal, oldVal){
if (newVal !== oldVal){
this.currentValue = newVal
}
}
},
// 生命周期钩子 (按照它们被调用的顺序)
beforeCreate(){}
,
created(){}
,
beforeMount(){}
,
mounted(){}
,
beforeUpdate(){}
,
updated(){}
,
activated(){}
,
deactivated(){}
,
beforeDestroy(){}
,
destroyed(){}
,
mounted(){
},
methods:{
},
// 渲染 (组件输出的声明式描述)
render(){
},
renderError(){
}
}
</script>
<style lang="scss" scoped >
.w-input {}
</style>