一、框架 / Vue
1.组件名
组件名为多个单词,并且用连接线(-)连接,避免与 HTML 标签冲突,并且结构更加清晰。
示例:
// 反例 export default { name: 'item' } // 正例 export default { name: 'page-article-item' }
2.组件文件
组件的名字应该始终是以连接线(-)连接的单词,一方面可与组件名一致,使项目更加清晰,另一方面这样的写法对编辑器引入也很友好。
示例:
// 反例 ├── index.html ├── main.js └── components ├── pageheader ├── pagearticle └── pageheader // 正例 ├── index.html ├── main.js └── components ├── page-header ├── page-article └── page-header
对于例如按钮、下拉框或表格这样的基础组件应该始终以一个特定的前缀开头,区别与其他业务组件。
示例:
// 反例 ├── index.html ├── main.js └── components ├── page-header ├── page-article ├── page-header ├── mazey-button ├── mazey-select └── mazey-table // 正例 ├── index.html ├── main.js └── components | ├── page-header | ├── page-article | └── page-header └── base ├── mazey-button ├── mazey-select └── mazey-table
3.Prop
定义 Prop 的时候应该始终以驼峰格式(camelCase)命名,在父组件赋值的时候使用连接线(-)。这里遵循每个语言的特性,因为在 HTML 标记中对大小写是不敏感的,使用连接线更加友好;而在 JavaScript 中更自然的是驼峰命名。
示例:
// 反例 // Vue props: { article-status: Boolean } // HTML <article-item :articleStatus="true"></article-item> // 正例 // Vue props: { articleStatus: Boolean } // HTML <article-item :article-status="true"></article-item>
Prop 的定义应该尽量详细的指定其类型、默认值和验证。
示例:
// 反例 props: ['attrM', 'attrA', 'attrZ'] // 正例 props: { attrM: Number, attrA: { type: String, required: true }, attrZ: { type: Object, // 数组/对象的默认值应该由一个工厂函数返回 default: function () { return { msg: '成就你我' } } }, attrE: { type: String, validator: function (v) { return !(['success', 'fail'].indexOf(v) === -1) } } }
4.v-for
在执行 v-for 遍历的时候,总是应该带上 key 值使更新 DOM 时渲染效率更高。
示例:
// 反例 <ul> <li v-for="item in list"> {{ item.title }} </li> </ul> // 正例 <ul> <li v-for="item in list" :key="item.id"> {{ item.title }} </li> </ul>
v-for 应该避免与 v-if 在同一个元素(例如:<li>
)上使用,因为 v-for 的优先级比 v-if 更高,为了避免无效计算和渲染,应该尽量将 v-if 放到容器的父元素之上。
示例:
// 反例 <ul> <li v-for="item in list" :key="item.id" v-if="showList"> {{ item.title }} </li> </ul> // 正例 <ul v-if="showList"> <li v-for="item in list" :key="item.id"> {{ item.title }} </li> </ul>
5.v-if / v-else-if / v-else
若同一组 v-if 逻辑控制中的元素逻辑相同,Vue 为了更高效的元素切换,会复用相同的部分,例如:value
。为了避免复用带来的不合理效果,应该在同种元素上加上 key 做标识。
示例:
// 反例 <div v-if="hasData"> <span>{{ mazeyData }}</span> </div> <div v-else> <span>无数据</span> </div> // 正例 <div v-if="hasData" key="mazey-data"> <span>{{ mazeyData }}</span> </div> <div v-else key="mazey-none"> <span>无数据</span> </div>
6.指令缩写
为了统一规范始终使用指令缩写,使用v-bind
,v-on
并没有什么不好,这里仅为了统一规范。
示例:
<input :value="mazeyUser" @click="verifyUser">
7.样式
为了避免样式冲突,整个项目要么全都使用 scoped 特性,要么使用 BEM 约定。
示例:
// 反例 <template> <button class="btn btn-sure">确认</button> </template> <style> .btn{ border: 1px solid #F1F1F1; } .btn-sure{ background-color: blue; } </style> // 正例 <!-- 使用 scoped 特性 --> <template> <button class="btn btn-sure">确认</button> </template> <style scoped> .btn{ border: 1px solid #F1F1F1; } .btn-sure{ background-color: blue; } </style> <!-- 使用 BEM(Block Element Modifier) 特性 --> <template> <button class="menu-btn menu-btn-sure">确认</button> </template> <style> .menu-btn{ border: 1px solid #F1F1F1; } .menu-btn-sure{ background-color: blue; } </style>
注意
不建议使用类似于 font-size-20
,color-666
,margin-top-20
这样的类,此时如果想把全局的color-666
颜色改成 #ccc
,不管是直接把 .color-666{color: #666;}
改成 .color-666{color: #ccc;}
,还是 全局搜索修改 class 名都很麻烦。本质上我认为 color-666
和直接写 style="color: #666;"
并没有区别。
8.单文件组件的顶级元素顺序
为了统一和便于阅读,应该按 <template>
、<script>
、<style>
的顺序放置。
示例:
// 反例 <style> /* CSS */ </style> <script> /* JavaScript */ </script> <template> <!-- HTML --> </template> // 正例 <template> <!-- HTML --> </template> <script> /* JavaScript */ </script> <style> /* CSS */ </style>
二、JavaScript
1.var / let / const
建议不再使用 var,而使用 let / const,优先使用 const。任何一个变量的使用都要提前申明,除了 function 定义的函数可以随便放在任何位置。
2.引号
建议不再使用双引号,静态字符串使用单引号,动态字符串使用反引号衔接。
示例:
// 反例 const foo = "后除" const bar = foo + ",前端工程师" // 正例 const foo = '后除' const bar = `${foo},前端工程师`
3.函数
匿名函数统一使用箭头函数,多个参数/返回值时优先使用对象的结构赋值。
示例:
// 反例 function getPersonInfo (name, sex) { // ... return [name, gender] } // 正例 function getPersonInfo ({name, sex}) { // ... return {name, gender} }
函数名统一使用驼峰命名,以大写字母开头申明的都是构造函数,使用小写字母开头的都是普通函数,也不该使用 new 操作符去操作普通函数。
4.对象
建议使用扩展运算符拷贝对象而不是 Object.assign(target, ...sources)
。
示例:
// 错误 const foo = {a: 0, b: 1} const bar = Object.assign(foo, {c: 2}) // 反例 const foo = {a: 0, b: 1} const bar = Object.assign({}, foo) // 正例 const foo = {a: 0, b: 1} const bar = JSON.parse(JSON.stringify(foo)) // 极好 // 根据具体情况使用扩展运算符/序列化/递归! const foo = {a: 0, b: 1} const bar = {...foo, c: 2}
对象尽量静态化,添加新属性使用 Object.assign(target, ...sources)
。
示例:
// 反例 const foo = {a: 3} foo.b = 4 // 正例 const foo = {a: 3} Object.assign(foo, {b: 4})
若有遍历对象的需求,优先使用 Map 结构。
示例:
// 反例 const myMap = { foo: 0, bar: 1 } for (let key in myMap) { // ... } // 正例 const myMap = new Map([]) for (let [key, value] of myMap.entries()) { // ... }
5.模块
统一使用 import / export 的方式管理项目的模块。
示例:
// lib.js export default {} // app.js import app from './lib'
import 统一放在文件顶部。
如果模块只有一个输出值,使用 export default
,否则不用。
6.循环
for (var i = 0; i < arr.length; i++) {}
这样的方式遍历不是很好,尤其当 arr 是 Dom 对象的时候,这样就会一直在访问 Dom 层,访问 Dom 层的代价是很大的。for (var i = 0, j=arr.length; i < j; i++) {}
这样的方式去用循环是比较好的,只会访问一次 Dom 层(不适用于 Dom 节点会动态更新的场景)。
7.eval
避免使用 eval
,如要进行字符串转化为对象,最好使用浏览器的内置方法来解析 JSON 数据,以确保代码的安全性和数据的合法性。如果浏览器不支持 JSON.parse()
,你可以使用 JSON.org 所提供的库。如果不得不使用 eval()
,可以尝试用 new Function()
来代替,在 new Function()
中运行的代码会在一个局部函数作用域内执行,因此源码中定义的变量不会自动变成全局变量。
三、HTML / CSS
1.标签
在引用外部 CSS 或 JavaScript 时不写 type 属性。HTML5 默认 type 为 text/css
和 text/javascript
属性,所以没必要指定。
示例:
// 反例 <link rel="stylesheet" href="//www.test.com/css/test.css" type="text/css"> <script src="//www.test.com/js/test.js" type="text/javascript"></script> // 正例 <link rel="stylesheet" href="//www.test.com/css/test.css"> <script src="//www.test.com/js/test.js"></script>
2.协议
省略协议头部声明,例如:http:
、https:
,且不加引号。
示例:
// 反例 background: url("http://www.test.com/img/test.png"); // 正例 background: url(//www.test.com/img/test.png);
3.选择器
选择器尽可能简单,能使用 .test
别使用 div.test
。
每个选择器和声明都要独立新行。
示例:
// 反例 p.test{ color: #000; } h1,h2,h3{ font-size: 12px; color: #666; } // 正例 .test{ color: #000; } h1, h2, h3{ font-size: 12px; color: #666; }
4.分号
每个声明最后都要加分号 ;
,即使是最后一个。
示例:
// 反例 h3{ font-size: 12px; color: #666 } // 正例 h3{ font-size: 12px; color: #666; }
5.命名
Class 和 ID 的命名应该语义化,通过看名字就知道是干嘛的;多个单词用连接线 -
连接。
示例:
// 反例 .testheader{ font-size: 20px; } // 正例 .test-header{ font-size: 20px; }
6.属性缩写
CSS 属性尽量使用缩写,提高代码的效率和方便理解。
示例:
// 反例 border-width: 1px; border-style: solid; border-color: #ccc; // 正例 border: 1px solid #ccc;
7.文档类型
应该总是使用 HTML5 标准。
示例:
<!DOCTYPE html>
8.table
应该避免使用 table 做页面布局,因为同样的布局使用 table 要多几倍的渲染时间;当然使用 table 做表格是完全正确的。
9.注释
应该给一个模块文件写一个区块注释。
示例:
/** * @module mazey/api * @author Mazey <mazey@mazey.net> * @description test. * */