前言
在项目开发中,个人的单打独斗式开发越来越少,团队合作越来越多。而在团队合作中,不同程序员之间的开发习惯是不一样的,这样会增加阅读其他成员代码困难。
为了能在团队协作中,输出可读性强、风格统一的代码,我们需要制定一些团队中的代码方面的规范。
HTML篇
html元素标记是我们再web上创建项目的基础。如果我们对初始的标记做的好,便于我们写成更容易扩展的css和JavaScript代码。
语义化
我们需要根据元素其被创造出来时的初始意义来使用它,而不是全文的 div
和 p
元素。
// bad
<div id='header' >
<div id='header-screen'>
<div id='header-inner'>
// good
<header>
<section>
<nav>
复制代码
文档规范
使用HTML5的文档声明类型 <!DOCTYPE html>
来开启标准模式。
若不添加该声明,浏览器会开启怪异模式,按照浏览器自己的解析方式渲染页面,那么,在不同的浏览器下面可能会有不同的样式。
meta信息
定义字符编码
我们统一使用 UTF-8
编码,避免乱码问题。
<meta charset="utf-8" />
复制代码
IE兼容模式(x-ua-compatible)
我们设置 x-ua-compatible
来强制浏览器的渲染方式,这里我们更多的使用IE的最新版本和 Chrome。
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
复制代码
结构、表现、行为三者分离
尽量在文档和模板中只包含结构性的 HTML;而将所有表现代码,移入样式表中;将所有动作行为,移入脚本之中。
HTML只关注内容
HTML只显示展示内容信息,不要引入一些特定的HTML结构来解决一些视觉设计问题,而是尽量通过css来解决。
// bad
<span class="text-box">
<span class="square"></span>
See the square next to me?
</span>
// css
.square {
display: inline-block;
width: 1rem;
height: 1rem;
background-color: red;
}
// good
<span class="text-box">
See the square next to me?
</span>
// css
.text-box:before {
content: "";
display: inline-block;
width: 1rem;
height: 1rem;
background-color: red;
}
复制代码
css篇
在设置样式时,我们会遇到一些问题:
选择器优选级。无论是ID还是类名,写选择器时,需要考虑优先级问题
位置依赖。选择器路径和HTML元素位置相关,意味着元素改变,样式也可能改变
多重继承。某类元素的样式来源有多个,某个来源发生变化,可能也会影响这个元素样式变化
我们可以采用一些方法来解决这些问题。
模块化css
模块化css和HTML标记一起使用,让标记更清晰,更“模块化”,便于理解。
当然,这样的方法很多,可能一个项目和一个方法契合,但另一个项目契合其他的方法,所以我们可以按照实际需求自主选择设计方法。
OOCSS(Object-Oriented CSS, 面向对象的CSS)
OOCSS方法有两个原则:
分离结构和外观。将外观定义为可复用的单元或皮肤
分离容器和内容。不将HTML元素作为样式的限制
<div class="toggle simple">
<div class="toggle-control active">
<h2 class="toggle-title">Title 1</h2>
复制代码
这里,simple
使用直角,切换simple
,可视为切换皮肤;toggle_title
用于设置文本样式,不用在意文本的元素是 div
还是h2
。
SMACSS(Scalable and Modular Architecture for CSS)
SMACSS,即模块化架构的可扩展CSS方法。会将样式系统分为5个不同的类别:
基础。即不添加CSS类别,HTML元素会展示什么样式
布局。把页面分为一些区域
模块。设计中的模块化、可复用的单元
状态。在特定状态或情况下,模块或布局的展示样式
主题。一个可选的视觉外观层,可以切换不同的主题
<div class="toggle toggle-simple">
<div class="toggle-control is-active">
<h2 class="toggle-title">Title 1</h2>
复制代码
SMACSS和OOCSS有很多的相似之处,除了SMACSS把代码划分类别外,最大的不同在于SMACSS使用子模块和is前缀的状态,而OOCSS使用皮肤。
BEM(Block Element Modifier, 块元素修饰符)
BEM方法,建议每个元素都添加有以下内容的css类名:
块名。所属组件的名称
元素。元素在块中的名称
修饰符。任何与块和元素相关的修饰符
<div class="toggle toggle--simple">
<div class="toggle_control toggle_control--active">
<h2 class="toggle_title">Title 1</h2>
复制代码
BEM的好处是我们可以清晰的理解这个类名的含义,当然,这会让类名看起来显得累赘、冗余。
单一职责原则
你创建的所有东西必须是单一的,高度聚焦的,为某个选择器的样式应该是为单一的目的创建的。
<div class="calendar">
<div class="primary-header">This is calendar.</div>
</div>
<div class="blog">
<div class="primary-header">This is blog.</div>
</div>
.primary-header {
color: red;
font-size: 2em;
}
复制代码
在上面的例子中, .primary-header
被用于 不止一个且不相关的元素上 ,这不满足我们单一职责原则。我们可以进行以下修改:
<div class="calendar">
<div class="primary-header">This is calendar.</div>
</div>
<div class="blog">
<div class="primary-header">This is blog.</div>
</div>
.primary-header {
color: red;
font-size: 2em;
}
blog .primary-header {
color: red;
font-size: 2em;
}
复制代码
但是,.primary-header会出现多重继承的问题,针对这个问题,我们可以给每个css类名添加单一的任务。
<div class="calendar">
<div class="calendar-header">This is calendar.</div>
</div>
<div class="blog">
<div class="blog-header">This is blog.</div>
</div>
.calendar-header {
color: red;
font-size: 2em;
}
.blog-header {
color: red;
font-size: 2em;
}
复制代码
Javascript 篇
命名
命名一般分为两种:
userName
UserName
变量命名
命名方式: 小驼峰式命名方法
命名规范: 类型+对象描述的方式。如果没有明确的类型,就可以使用名词+对象描述。
推荐写法:
并且,我们在变量命名时,应该要使变量名具有代表意图的象征,使人易于搜索并且容易理解。
const sUserName = 'tom'
const isRead = true
// 使用名词作前缀
const userTable = 'talbe'
// 若描述对象是复数时,需要添加s
const userTables = ['talbe1', 'table2']
复制代码
常量命名
命名规范: 全部大写+下划线
const USER_ADDR = '北京'
复制代码
函数命名
命名方式: 小驼峰式命名方法
命名规范: 动词+方法描述的方式。
推荐动词:
function setName(name) {
this.name = name;
}
function getName() {
return this.name;
}
复制代码
若是构造函数,则使用大驼峰式命名方法。
function Student(name, age) {
this.name = name;
this.age = age;
}
const oStudent = new Student('Tom', 18);
复制代码
类及成员命名
在ES6中,我们可以通过class来创建类,并设置私有/公有属性。
公有属性:同变量命名方法/函数命名方法。
私有属性:前缀(_)+公有属性命名方法。
class Student {
static getId(){
console.log('getId')
}
private _name = 'Tom';
public getName() {
return this._name;
}
}
复制代码
变量声明
谨慎使用全局变量
全局变量是魔鬼。
如果你不小心,在代码的某一处修改了全局变量,可能会导致依赖全局变量的其它模块出错,并且出错原因难以找到。
那么,我们应该怎么解决呢?
1.尽可能创建一个全局变量,让其他对象和函数存在其中。
// bad
const like = 'football';
function likeDo(){
alert(like);
}
// good
const myInfo={
like:'football',
likeDo:function(){
alert(this.like);
}
}
复制代码
2.使用模块模式
在ES6中,我们通过import/export
产生模块,可以将需要的信息放置在一个模块中,几乎可以完全屏蔽掉全局变量的使用。
// myInfo.js
export const like = 'football';
export function likeDo() {
alert(this.like);
}
// test.js
import { likeDo, like } from 'myInfo';
复制代码
3.闭包
当然,有时我们也可以通过闭包来减少全局变量信息。不过,我们在使用闭包时,也需要注意内存泄漏的问题。
const myInfo = (function () {
const like = 'football';
return {
like,
likeDo: () => {
alert(like);
}
}
})();
复制代码
使用let/const来声明变量
以前我们使用var
来声明变量,但是ES6版本以后,应该尽量使用 let/const
来声明变量。
我们在使用var
时,会存在变量提升的情况,这可能会导致一些误解;并且,当 var
作用于全局作用域时,会创建一个新的全局变量作为全局对象的属性,这可能会无意中覆盖一个全局变量。
// 浏览器中
var RegExp = 'hello';
console.log(window.RegExp) // hello
const RegExp = 'hello';
console.log(window.RegExp) // ƒ RegExp() { [native code] }
复制代码
使用严格等
当我们使用==
来判断两个变量相等时,若两个变量不是同一类型,会触发JavaScript的强制类型转换,出现和我们预期不相符的结果(详细情况可以看这里)。而我们使用严格等===
则不会出现这种情况。
// bad
0 == '0' // true
0 == '' // true
// good
0 === '0' // false
0 === '' // false
复制代码
不使用eval()函数
eval
函数可计算某个字符串,并 执行其中的JavaScript代码 ,这会带来安全隐患。
代码风格及检查
上面可以算是一些强制性高的内容,但是我们仍旧会面临一些灵魂拷问:
1.缩进用空格还是制表符?空格的话,用两个空格还是四个空格?
2.句末是否需要添加分号?
3.每行代码最多写100行还是80行?
- ...
这都是一些可以让程序员争论不休的问题,每一个问题都可以列出无数个正反理由。在这里我不想去说哪种方法绝对正确,毕竟再烂的代码,只要合法,JavaScript引擎都能正确执行。
但是,为了我们的代码能够便于阅读,我们需要统一风格,并使用各种工具进行检查。
JSLint
早期,我们使用JSLint
来检查我们的JavaScript代码质量。它会读取源文件并进行扫描,如果有问题会返回一个消息进行描述并指明该问题所在源文件中的大概位置。
但是, JSLint
不支持规则自定义,必须遵守作者提供的规则。
JSHint
JSHint
基于JSLint
开发,能灵活的自定义规则。但是,它是基于 JSLint
开发的,自然原有的一些问题它也继承下来了,JSHint
对ES6的支持度不够高,且不支持JSX。
ESLint
ESLint
是 Nicholas C. Zakas
在2013年开发的JavaScript代码静态分析工具。它的初衷就是能让开发者能自定义自己的linting rules
。
它提供了一套相当完善的插件机制,可以自由的扩展,动态加载配置规则。它既具有JSHint
的高度可配置性,同时也通过插件机制完整支持了ES6语法以及JSX,任意阶段的ECMAScript
特性。
这也是我们现阶段正在使用的工具。
TSLint
TSLint
用于对TypeScript做代码静态分析,后面我们统一使用ESLint
,并在ESLint
中加入TSLint
检测插件。
Prettier
Prettier
是一个代码格式化工具,我们可以通过自定义的规则,使输出代码保持风格一致,比如针对最大行数自动换行,句末添加自动分号等。
我们可以将 Prettier
和 ESLint
一起使用。
总结
我们简单总结了在项目中,针对HTML、CSS、JavaScript的不同原则、规范及检查工具。
当然,这不是一份某种意义上的决定正确的方案,每个团队每个项目都可以设计出自己独有的规范。只要能提高我们的项目的代码质量,便于团队之间的沟通协作,一切方案都是可行的。
最后
如果你现在也想学习前端开发技术,在学习前端的过程当中有遇见任何关于学习方法,学习路线,学习效率等方面的问题,你都可以加入到我的Q群中:前114中6649后671,里面有许多前端学习资料以及2020大厂面试真题 点赞、评论、转发 即可免费获取,希望能够对你们有所帮助。
网友评论