前端代码规范
HTML规范
1.img标签要写alt属性
表示图片想要表达的意思,当图片无法显示的时候会显示文字
2.单标签不要写闭合
<img scr='hahaha.jpg'></img> //应该去掉</img>
<input type='text' value=''/> //应该去掉末尾的/
但是如果用React写jsx模板,它就要求每个标签都要闭合,但是它始终不是原生html
3.自定义属性要用data-开头
4.td要写在tr里,li要写在ul/ol里
有些浏览器可能不会帮你矫正,各家浏览器处理方式不统一
<table> //td没有放在tr里
<td></td>
</table>
5.ul和ol的子元素只能是li
在ul或ol里面直接写一个div或span是不规范的
因为ul或ol的直接子元素的display:list-item,如果加上一个div,不同浏览器的处理方式不同,同一个样式在不同浏览器中可能会有不同的表现
6.section里面要有标题标签
section/aside/article/nav这种标签,里面需要写一个h1/h2/h3之类的标题标签,因为这四个标签能够划分章节,他们是独立的章节,需要有标题
如果UI里面没有标题,那就可以写一个隐藏的标签,出于SEO的目的,不能display:none,要用一些特殊的处理方式
<style>
.hidden-text{
position:absolute;
left:-9999px;
top:-9999px;
}
</style>
<section>
<h1 class='hidden-text'>
Listing Detail
</h1>
</section>
7.使用section标签增强SEO
使用section可以分章节
8.行内元素里面不能使用块级元素
在行内元素里面嵌套块级元素是不合法的
如果在a标签里面嵌套块元素,可能会导致点击无法跳转页面
解决:可以把inline元素的display改成block
9.每个页面都要写<!DOCType html>
将页面设置为标准模式,如果不这么写则默认为怪异模式
标准模式和怪异模式
浏览器解析css代码有两种模式:标准模式、怪异模式
标准模式:浏览器按照w3c标准解析代码
怪异模式:浏览器按照自己的方式去解析代码,因为每个浏览器都不一样,所以称为怪异模式
标准模式和怪异模式的区别
-
盒模型:
标准模式:标准盒子模型
宽度:content的宽度
外盒尺寸:width+padding *2+border *2+margin *2
元素宽度:width+padding *2+border *2+margin *2
怪异模式:IE盒子模型
宽度:content+border *2+padding *2
外盒尺寸:width+margin*2
元素宽度:width
-
图片元素的垂直对齐方式
对于inline元素和table-cell元素,标准模式下vertical-align属性默认取值是baseline;在怪异模式下,table单元格中的图片的vertical-align属性默认取值是bottom。因此在图片底部会有几像素的空间
-
元素中的字体
CSS中,对于font的属性都是可以继承的。怪异模式下,对于table元素,字体的某些元素将不会从body等其他封装元素继承中的得到,特别是font-size属性
-
内联元素的尺寸
标准模式下,inline元素无法自定义大小;
怪异模式下,定义这些元素的width、height属性可以影响这些元素显示的尺寸
-
元素的百分比高度
CSS中对于元素的百分比高度规定:百分比为元素包含块的高度,不可为负值;如果包含块的高度没有显示给出,该值等同于auto,所以百分比的高度必须是在元素有高度声明的情况下使用。
当一个元素使用百分比高度是,标准模式下,百分比高度被准确应用,怪异模式下,百分比高度被准确应用高度取决于内容变化 -
元素溢出的处理
标准模式下,overflow取值默认为visible;在怪异模式在,该溢出会被当做扩展box来对待,即元素的大小由内容决定,溢出不会裁剪,元素框自动调整,包含溢出内容
10.要用table布局写邮件模板
邮箱客户端多种多样,对HTML/CSS的支持也不一样,所以不能用高级的布局(flex,float,absolute等),需使用较初级的table以达到兼容性最好的效果
邮件模板不能用媒体查询,不能写script,不能写外联样式,可以先写外联,在通过一些工具生成对应的内联HTML
为了兼容移动端和pc端,应该设置最大宽度(比如最外面的table宽度100%,里面的table有一个max-width:600px,相对于外面的table居中。这样在PC上最大宽度就为600px,而在手机客户端上宽度就为100%)
中间没保存不见了
11.排版规范
不管是JS还是CSS,把缩进都调整成四个空格
每个属性名冒号后面要加一个空格
每个选择器前面也要加一个空格
多个选择器共用一个样式时,每个选择器独占一行
12.属性值规范
如果值是0,则通常不用带单位
但是有一个特例,就是和时间有关的单位都要带上s
色值用16进制,少用rgb
因为rgb是一个函数,他还要计算一下转化,透明的还要设置rgba
注意border:none和0的区别
border:none 即说明不存在,页面不会渲染,即不会消耗内存值
border:0 页面会对其进行渲染,会占用内存
13.font-family的设置
注意使用系统字体的对应的font-family名称,如SFUIText Font这个字体,在Safari是-apple-system,而在Chrome是BlinkMacSystemFont,所以font-family可以这么写
font-family{
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
}
14.不要设置太大的z-index
开发过程中很难统一,尽量保持自己的页面业务逻辑的z-index为各位数
15.合并属性
比如margin-right,margin-left这些可以合并的属性,一般写成合并形式,让代码看起来更整洁
16.注意float/absolute/fixed会定位强制设置成block
比如设置了浮动,目标元素就会具有块级盒模型的特点,即使设置display:inline也是没有用的,默认为display:block了
如果是display:flex,那么float将会被忽略
17.清除浮动
一般采用clearfix
.clearfix:after{
content:"";
display: table;
clear:both; //清除元素两端的浮动
}
18.引号的使用
font-family一般来说不需要添加引号
但是如果字体名称刚好是关键字,就要加上双引号
font-family: "inherit", "serif", "sans-serif", "monospace", "fantasy", and "cursive"
background 的url
一般来说可以不加,但是当url里面有特殊字符没有转义的话,就要加上双引号
background-url: url(//cdn.test.me/hello world.jpg)
所以一般我们都是要加上双引号,可以兼容
单引号还是双引号
普遍推荐HTML写双引号,css写单引号
19.css动画规范
不要用all属性做动画
在不同浏览器下可能不太兼容,一般要用哪个属性做动画就用写那个,如果有多个那就隔开
transition: transform 2s linear,
opacity 2s linear;
使用transform替代position做动画
能用transform做动画就不用left这些,因为transform不会造成重绘,性能比position高很多
偏向使用css动画代替js动画
回流与重绘
一个页面从加载到完成,首先是构建DOM树,然后根据DOM节点的几何属性形成render树(渲染树),当渲染树构建完成,页面就根据DOM树开始布局了,渲染树也根据设置的样式对应的渲染这些节点。
在这个过程中,回流与DOM树,渲染树有关,重绘与渲染树有关
回流:比如我们增删DOM节点,修改一个元素的宽高,页面布局发生变化,DOM树结构发生变化,那么肯定要重新构建DOM树,而DOM树与渲染树是紧密相连的,DOM树构建完,渲染树也会随之对页面进行再次渲染
重绘:当你给一个元素更换颜色,这样的行为是不会影响页面布局的,DOM树不会变化,但颜色变了,渲染树得重新渲染页面
减少回流的方法
- DOM的增删行为:添加节点的时候,最好使用文档碎片的方式添加,减少回流
- 几何属性的变化:如果要改变多个几何属性,就将他们放入一个类中,然后通过添加类的方法添加属性,这样只引起一次回流
- 元素位置的改变:一般不修改margin和padding之类的操作,而是使用定位让其脱离文档流后改变位置
- 获取元素的偏移量属性:获取scrollTop之类的属性,浏览器为了获取准确值会重新回流一次
- 页面初次渲染:无法避免
- 浏览器窗口尺寸的变化:无法避免
文档碎片
DocumentFragment 表示一个没有父级文件的最小文档对象。它被当做一个轻量版的 Document 使用,用于存储已排好版的或尚未打理好格式的XML片段。最大的区别是因为DocumentFragment不是真实DOM树的一部分,它的变化不会引起DOM树的重新渲染的操作(reflow) ,且不会导致性能等问题
直接操作DOM:
使用DocumentFragment一次性添加:
使用文档碎片添加节点:
fragment = document.createDocumentFragment(); fragment.appendChild(document.createElement("li"));
20.不要断词
hyphens:auto; //断词的属性,一般不用,因为断的不彻底
21.不要设置图标字体font-family
不在每一个图标里面都添加一个font-family:”icon-font“
而是设置一个类,相关的font-family都设置在这个类里面
22.设置常见样式reset
修改各个浏览器的默认样式
23.图片压缩
https://tinypng.com/
24.正确使用background和img
如果是头图直接展示的图片则用img标签,可以设置alt增强SEO
如果是背景图就用background,可以设置background-position:center center
25.响应式布局的规范
一般不杂合着使用rem,文字要么全用要么全不用
26.适当使用:before和:after
可以用来画页面上一些视觉上的辅助性元素,比如三角形,短竖线等
但是正常的文本元素就一般不用
27.少用absolute定位
absolute扩展性很差,性能好
float扩展性较好,但是性能相对较差
28.少用inline-block布局
inline-block是行内元素,在里面添加块元素的话不合法,详见HTML规范中的第8点
29.图片的居中和宽高设定
UI给的图片一般是固定的,但是现实中图片的长宽不一,所以应该借助JS来拉伸图片
<div class="img-container"> <img src="test.jpg" alt onload="resizeImg(this, '400px', '300px')"></div>
30.移动端提高可点区域范围
31.不设置input的line-height
可能会导致safari的光标变得很大,所以一般不用此方法垂直居中,而是使用padding
32.移动端要禁止body滑动
33.行内元素可以直接设置margin-left和margin-right
可以把行内元素撑开
JS规范
1.变量命名
变量名不应该过短,应该起的有意义
不能取计算机术语
变量名应该对仗明确,比如up/down等
警惕临时变量,少用temp这类变量名
bool变量
建议布尔变量不用以is/do之类的开头
另外变量名不要使用否定的名词,如notOk,notReady,因为否定的词取反的时候就会比较奇怪,如if(!notOk). 要使用肯定的布尔变量名
变量名使用正确的语法
不使用中文拼音
2.声明变量时要赋值
可以让人提前知道变量所表示的数据类型,也有利于JS解释器提前做一些优化处理
3.函数的返回值类型要确定
4.不给变量赋值undefined
undefined表示未定义,而定义了一个变量又说未定义可能会造成歧义
我们经常使用undefined来判断变量是否定义
如果要赋值的值是空值,则对象赋null,数字赋NAN,字符串赋空字符串
函数的返回值也不要显式地return undefined
5.排版规范
逗号后面带个空格
双目运算符中间两边都要带空格
一行一般不超过100个字符,太长了就换行
6.使用=代替
会带上类型转化,所以一般不用
要用===强类型进行判断
7.减少魔数
对一些比较重要的变量起一个名字
8.不要让代码暴露在全局作用域下运行
在全局作用域下,变量查找的时间会更长
会污染全局作用域,有时候会造成一些意想不到的结果
9.var/let/const的使用
使用let的好处
- 避免变量重复定义
- for循环的变量作用域是独立的
const适合给常量取个名字,或者是定义一些不需要的变量防止被修改
10.简洁代码
使用三目运算符代替简单的if-else
使用箭头函数代替简单的函数
11.避免执行时间过长的JS代码
比如进行大量的DOM操作,可以改用文档碎片进行操作
12.注释(与css类似)
13.代码不要嵌套太深
14.对于常用的属性进行缓存
比如window.location这个属性被多次调用,就可以定义一个局部变量储存他,加快查找时间
15.尽量不要在JS里面写css
在修改代码的适合比较麻烦,需要同时注意css和JS两个地方的代码
一般使用添加类的方式添加css样式
但是动态计算position的值这些只能用JS实现
16.在必要的地方添加非空判断
添加非空判断提高代码的稳健性,告诉调用者传的为空就不用处理,也可以找出后台数据出错的地方
17.不用for in循环数组
如果在对数组遍历时使用for in循环,并且循环对象的原型中添加了某个函数,那么遍历出来的元素会包含这个原型上添加的函数,导致遍历出现问题
所以一般使用forEach或map
18.分号规范
可以不加,但是在开发过程中最好还是加上,不容易出错
19.使用location跳转需要先转义
对于那些根据用户输入内容做跳转,需要先把用户内容做转义,如下有问题的代码:
let searchContent = form.search.value.trim();window.location.href = `/search?key=${searchContent}`;
如果用户输入了一个#号如门牌号,将会导致#后面的内容当作锚点了,或者用户可能会输入一个空格。所以如果不确定内容的东西需要先encode转义一下,如下代码
let searchContent = encodeURIComponent(form.search.value.trim());window.location.href = `/search?key=${searchContent}`;
20.跳转尽量不要使用onclick跳转
不利于SEO
跳转可以使用a标签去跳转,还可以控制是否打开新页面
移动端中也不用担心onclick是否延迟
21.不要直接使用localStorage
Safari的隐身模式本地储存会被禁用,所以无法往localStorage写入数据
但是谷歌不会被禁用,所以应该做一个兼容,判断是否为隐身模式,是的话就用cookie,否的话则用localStorage
Data.hasLocalStorage = true;try{ window.localStorage.trySetData = 1;}catch(e){ Data.hasLocalStorage = false;}setLocalData: function(key, value){ if(Data.hasLocalStorage){ window.localStorage[key] = value; } else{ util.setCookie("_LOCAL_DATA_" + key, value, 1000); }},getLocalData: function(key){ if(Data.hasLocalStorage){ return window.localStorage[key]; } else{ return util.getCookie("_LOCAL_DATA_" + key); }}
22.使用简单的转化
把字符型转为整型可以用+号
+相当于Number
praseInt与Number最大的区别是praseInt可以将10px转化为10,而Number则转化为NAN
把小数去掉尾数转成整型,可以使用>>0
let _row = Math.floor(index / columns);let row = parseInt(index / columns);可以改写成:let row = index / columns >> 0;
转成boolean值用 !!
23.注意返回false的变量
在if判断里面为false的值:0、false、“”、undefined、null、NAN
所以可以直接用if(array.length){ }判断
但是判断一个变量有没有定义还是要写成:
if (typeof foo !== “undefined”) {} //防止上述的值被认为没有定义
24.使用Object.assgin简化数据赋值
将要添加或者要修改的属性放在一个对象里面,然后在将这个对象与原来的对象用assign合在一起
25.调试完去掉无关的console
26.注意this的指向
27.使用正则表达式做字符串处理
正则表达式可以很方便地处理字符串,通常只要一行代码就搞定了。例如去掉全局的某一个字符,如去掉电话号码的-连接符
phoneNumer = phoneNumber.replace(/\-/g, “”);
28.保持复用模块的观念
将一个大函数拆成多个小函数,让主函数的逻辑变得清晰
29.注意label事件会触发两次
如果label里面有input时,监听label的事件会触发两次
<label> <input type="radio" name="fruit" value="apple"> <span>apple</span></label>
比如给label绑定一个点击事件,点击span时,label会触发input,input又会冒泡到label