https://blog.csdn.net/Raleway/article/details/104268283/
https://blog.csdn.net/qq_43277404/article/details/104613354
https://blog.csdn.net/come0across/article/details/104895118
ng-if 跟 ng-show/hide 的区别有哪些?
第一点区别是,ng-if
在后面表达式为 true
的时候才创建这个 dom
节点,控制dom节点的增删除来实现显示隐藏,ng-show/ng-hide 是初始时就创建了,用 display:block
和 display:none
来控制显示和不显示。
第二点区别是,ng-if
会(隐式地)产生新作用域,ng-switch
、 ng-include
等会动态创建一块界面的也是如此。
这样会导致,在 ng-if
中用基本变量绑定 ng-model
,并在外层 div
中把此 model
绑定给另一个显示区域,内层改变时,外层不会同步改变,因为此时已经是两个变量了。
ng-show
不存在此问题,因为它不自带一级作用域。
避免这类问题出现的办法是,始终将页面中的元素绑定到对象的属性(data.x)而不是直接绑定到基本变量(x)上。
ng-repeat迭代数组的时候,如果数组中有相同值,会有什么问题,如何解决?
会提示 Duplicates in a repeater are not allowed
. 加 track by $index
可解决。当然,也可以 trace by
任何一个普通的值,只要能唯一性标识数组中的每一项即可(建立 dom
和数据之间的关联)
css优先级,属性选择器的优先级在哪
0.类型选择器(如, h1)和伪元素(如, ::before)
1.类选择器,属性选择器,伪类(如,:hover)
3.ID选择器
通用选择器(universal selector)(*), 组合子(combinators) (+, >, ~, ' ') 和 否定伪类(negation pseudo-class)(:not()) 对特异性没有影响。(但是,在 :not() 内部声明的选择器是会影响优先级,在计算选择器数量时还是会把其中的选择器当做普通选择器进行计数)。
4.给元素添加的内联样式总会覆盖外部样式表的任何样式 ,因此可看作是具有最高的优先级。
权重记忆口诀。一个元素名,或者伪元素+1,一个属性选择器/class或者伪类+10,一个id+100,一个行内样式+1000。
**!important 规则例外
当在一个样式声明中使用一个!important 规则时,此声明将覆盖任何其他声明。**
直接定位的样式权重大于继承的样式,无论继承的规则的特异性(优先级)如何。
垂直水平居中的几种实现方式
一、固定宽高:
(1)定位 + margin-top + margin-left
.box-container{
position: relative;
width: 300px;
height: 300px;
}
.box-container .box {
width: 200px;
height: 100px;
position: absolute;
left: 50%;
top: 50%;
margin-top: -50px; /* 高度的一半 */
margin-left: -100px; /* 宽度的一半 */
}
(2)定位 + margin
.box-container{
position: relative;
}
.box {
width: 100px;
height: 100px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
(3)absolute + calc,存在兼容问题(依赖calc的兼容性)
.box-container{
position: relative;
}
.box {
position: absolute;;
top: calc(50% - 50px);
left: calc(50% - 50px);
}
二、未知宽高
1、transform 方案: 存在兼容问题:
.box {
position: relative;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
2、flexbox 方案: 存在兼容问题
.box-container {
display: flex;
justify-content: center;
align-items: center;
}
3、display: table-cell 无兼容性问题
.box {
position: relative;
width: 300px;
height: 300px;
border: 1px solid red;
display: table-cell;
text-align: center;
vertical-align: middle;
}
number.toFixed()精度丢失----二进制浮点数表示法并不能精准表示十进制分数!JS采用二进制表示法,可以精确地表示二进制分数(1/2),但不能表示十进制分数(1/10)和像0.1这样的小数。
Math.round()四舍五入正确
Math.pow(2,5)求2的5次幂
保留小数的正确操作:
function toFixed(number,fractionDigits){
var times = Math.pow(10, fractionDigits);
var roundNum = Math.round(number * times) / times;
return roundNum.toFixed(fractionDigits);
}
3==true 打印出什么
会打印出false,这里会将true转变成1
Number 和 String 或者 Bool 类型比较,会对String 或者 Bool 类型进行ToNumber()转换
判断变量是不是数组的几个方法
var a=[];
a.constructor===Array //true
a instanceof Array === true //true
⚠️ 注意:以上方法在跨frame时会有问题,跨frame实例化的对象不共享原型
解决:
Object.prototype.toString.call(a) // "[object Array]"
Array.isArray(a) //true
原型 与 prototype属性
1、原型:
JavaScript的对象中都包含了一个" [[Prototype]]"内部属性,这个属性所对应的就是该对象的原型。对象从原型继承方法与属性。原型可能也有原型,这种关系被称为原型链。
"[[Prototype]]"作为对象的内部属性,是不能被直接访问的。所以为了方便查看一个对象的原型,大多数现代浏览器还是提供了一个名为"__proto__"这个非标准(不是所有浏览器都支持)的访问器(ECMA引入了标准对象原型访问"Object.getPrototype(object)")。
原型是由构造器函数创建的。从原型继承的方法与属性是在构造器函数中定义的。
2、prototype属性:
prototype属性并不指向当前对象的原型对象(原型对象是一个内部对象,应当使用 __proto__ 访问)。prototype属性是继承成员被定义的地方。
常见的对象定义模式是,在构造器(函数体)中定义属性、在 prototype 属性上定义方法。(在prototype属性中定义属性会不够灵活)
发现的比较奇异的点:一个变量不是函数的话默认没有 prototype属性,是函数的话默认就有 prototype属性,并且prototype对象中的constructor属性就是它本身
CSS和JS的位置会影响页面效率,为什么?
css在加载过程中不会影响到DOM树的生成,但是会影响到Render树的生成,进而影响到layout,所以一般来说,style的link标签需要尽量放在head里面,因为在解析DOM树的时候是自上而下的,而css样式又是通过异步加载的,这样的话,解析DOM树下的body节点和加载css样式能尽可能的并行,加快Render树的生成的速度。
js脚本应该放在底部,原因在于js线程与GUI渲染线程是互斥的关系,如果js放在首部,当下载执行js的时候,会影响渲染行程绘制页面,js的作用主要是处理交互,而交互必须得先让页面呈现才能进行,所以为了保证用户体验,尽量让页面先绘制出来。
非对称加密算法:RSA,DSA/DSS 需要两个密钥:公开密钥和私有密钥;公开密钥与私有密钥是一对。如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。主要是用来保护传输客户端生成的用于对称加密的随机数私钥
对称加密算法:AES,RC4,3DES,IDEA 特点是文件加密和解密使用相同的密钥加密;对称加密算法使用起来简单快捷,密钥较短,且破译困难。除了数据加密标准(DES),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的加密性好,而且对计算机功能要求也没有那么高。
HASH算法:BASE64、MD5、SHA、HMAC 是一种单向算法,用户可以通过hash算法对目标信息生成一段特定长度的唯一hash值,却不能通过这个hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。比如在确认握手消息没有被篡改时使用 ;
常用Java加密算法/HASH算法:
1.BASE64 (严格来说属于编码格式,而非加密算法):是网络上最常见的用于传输8bit字节代码的编码方式之一。base64编码可用于在http环境下传递较长的标识信息,采用base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
2.MD5(信息摘要算法):用于确保信息传输完整一致,又名杂凑算法,摘要算法、哈希算法;将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理。广泛用于加密和解密技术,常用于文件校验,不管文件多大,经过md5后都能生成唯一的MD5值。比如ISO校验,把ISO经过MD5后产生的MD5值,一般下载linux-ISO会看到下载链接旁边放着MD5的串,就是用来验证文件是否一致。
MD5算法具有以下特点:
1>压缩性:任意长度的数据,算出的MD5值长度都是固定的。
2>容易计算:从原数据计算出MD5值很容易。
3>抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
4>弱抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
5>强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。
3.SHA(安全散列算法):主要适用于数字签名标准里面定义的数字签名算法。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可理解为取一串输入码,并把他们转为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。散列函数值可以说是对明文的一种“指纹”或“摘要”所以对散列值的数字签名就可以视为对此明文的数字签名。
SHA-1与MD5的比较:二者均由MD4导出,SHA-1和MD5彼此很相似。但还有以下几点不同:
1>对强行攻击的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。SHA-1对强行攻击有更大的强度。
2>对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
3>速度:在相同的硬件上,SHA-1的运行速度比MD5慢。
4.HMAC(散列消息鉴别码):基于密钥的Hash算法的认证协议,它实现的原理是,用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传出,接收方利用与发送方共享的密钥进行鉴别认证等。
缓存分类:
一、强缓存
强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。
1.Expires
缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间,需要和Last-modified结合使用。Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。
Expires 是 HTTP/1 的产物,受限于本地时间,如果修改了本地时间,可能会造成缓存失效。Expires: Wed, 22 Oct 2018 08:41:00 GMT
表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,需要再次请求。
2、Cache-Control
在HTTP/1.1中,Cache-Control是最重要的规则,主要用于控制网页缓存。比如当Cache-Control:max-age=300
时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。
Cache-directive | 说明 |
---|---|
public | 所有内容都将被缓存(客户端和代理服务器都可缓存) |
private | 内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存) |
no-cache | 客户端缓存内容,是否使用缓存则需要经过协商缓存来验证决定。表示不使用 Cache-Control的缓存控制方式做前置验证,而是使用 Etag 或者Last-Modified字段来控制缓存。需要注意的是,no-cache这个名字有一点误导。设置了no-cache之后,并不是说浏览器就不再缓存数据,只是浏览器在使用缓存数据时,需要先确认一下数据是否还跟服务器保持一致。 |
no-store | 所有内容都不会被缓存到缓存或 Internet 临时文件中,不使用强制缓存,也不使用协商缓存 |
must-revalidation/proxy-revalidation | 如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证 |
max-age=xxx (xxx is numeric) | 缓存的内容将在 xxx 秒后失效, 这个选项只在HTTP 1.1可用, 并如果和Last-Modified一起使用时, 优先级较 |
s-maxage(单位为s) | 同max-age作用一样,只在代理服务器中生效(比如CDN缓存)。比如当s-maxage=60时,在这60秒中,即使更新了CDN的内容,浏览器也不会进行请求。max-age用于普通缓存,而s-maxage用于代理缓存。s-maxage的优先级高于max-age。如果存在s-maxage,则会覆盖掉max-age和Expires header |
max-stale | 能容忍的最大过期时间。max-stale指令标示了客户端愿意接收一个已经过期了的响应。如果指定了max-stale的值,则最大容忍时间为对应的秒数。如果没有指定,那么说明浏览器愿意接收任何age的响应(age表示响应由源站生成或确认的时间与当前时间的差值)。 |
min-fresh | 能够容忍的最小新鲜度。min-fresh标示了客户端不愿意接受新鲜度不多于当前的age加上min-fresh设定的时间之和的响应。 |
Cache-Control是关于浏览器缓存的最重要的设置,因为它覆盖其他设置,比如 Expires 和 Last-Modified。另外,由于浏览器的行为基本相同,这个属性是处理跨浏览器缓存问题的最有效的方法。
no-cache 指强制更新,一般用于html文档,因为html当中引用了很多img、css和js资源,必须到服务器获取最新的html文档,以便查看这些引用资源是否有了更新。
private 指超时更新,主要用于img、js、css等大文件,当上述html没有发生变化时,那我们就判断一下这些大文件的max-age,看看有没有过期,max-age是一个倒计时,指的就是文件的有效期,通常数值会很大,十几小时甚至几天时间,如果还有效的话就直接加载。
验证的方式为浏览器发送一个包含If-None-Match:ETag 的空数据包到服务器,这里的ETag是这个html文档在本地缓存中的哈希值。当服务器收到这个请求之后,会把浏览器请求的ETag 和服务器上最新的ETag进行比对,若没有变化,就返回一个包含304状态码的空数据包,浏览器接到这个包之后会直接从缓存中读取html加载到页面,若有变化,则服务器返回最新的html文件,浏览器再根据这个新的html去请求新的资源。
关键结论
打开新窗口 | 如果指定cache-control的值为private、no-cache、must-revalidate,那么打开新窗口访问时都会重新访问服务器。而如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器,例如:Cache-control: max-age=5 表示当访问此网页后的5秒内不会去再次访问服务器. |
在地址栏回车 | 如果值为private或must-revalidate,则只有第一次访问时会访问服务器,以后就不再访问。如果值为no-cache,那么每次都会访问。如果值为max-age,则在过期之前不会重复访问。 |
按后退按扭 | 如果值为private、must-revalidate、max-age,则不会重访问,而如果为no-cache,则每次都重复访问. |
按刷新按扭 | 无论为何值,都会重复访问. |
3.Expires和Cache-Control两者对比
其实这两者差别不大,区别就在于 Expires 是http1.0的产物,Cache-Control是http1.1的产物,两者同时存在的话,Cache-Control优先级高于Expires;在某些不支持HTTP1.1的环境下,Expires就会发挥用处。但他存在着一个时差bug,可以利用他进行非法登录,容易造成安全隐患,现在除了用它来标记失效,已经很少用到它了。
强缓存判断是否缓存的依据来自于是否超出某个时间或者某个时间段,而不关心服务器端文件是否已经更新,这可能会导致加载文件不是服务器端最新的内容,那我们如何获知服务器端内容是否已经发生了更新呢?此时我们需要用到协商缓存策略。
二、协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程,主要有以下两种情况:
1.Last-Modified和If-Modified-Since
浏览器在第一次访问资源时,服务器返回资源的同时,在response header中添加 Last-Modified的header,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header;
Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
浏览器下一次请求这个资源,浏览器检测到有 Last-Modified这个header,于是添加If-Modified-Since这个header,值就是Last-Modified中的值;服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200。
但是 Last-Modified 存在一些弊端:
既然根据文件修改时间来决定是否缓存尚有不足,能否可以直接根据文件内容是否修改来决定缓存策略?所以在 HTTP / 1.1 出现了 ETag
和If-None-Match。
2.ETag和If-None-Match
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。如果服务器发现ETag匹配不上,那么直接以常规GET 200回包形式将新的资源(当然也包括了新的ETag)发给客户端;如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。
3.两者之间对比:
Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。
三、缓存机制
强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。具体流程图如下:
看到这里,不知道你是否存在这样一个疑问:如果什么缓存策略都没设置,那么浏览器会怎么处理?
对于这种情况,浏览器会采用一个启发式的算法,通常会取响应头中的 Date 减去 Last-Modified 值的 10% 作为缓存时间。
四、用户行为对浏览器缓存的影响
Cache-control: no-cache
(为了兼容,还带了 Pragma: no-cache
),服务器直接返回 200 和最新内容。1、浏览器先查看浏览器缓存,若缓存中有,请略过中间步骤,直接跳到第9步。若没有,则按照以下步骤进行。
2、浏览器从url中解析出服务器的主机名,并将主机名转换成服务器的IP地址。
3、浏览器从url中解析出端口号,默认80,HTTPS默认端口443。
4、浏览器建立一条与服务器的TCP/IP连接,三次握手和四次挥手。
5、浏览器通过TCP/IP连接向服务器发送HTTP请求,请求数据包。
6、服务器处理HTTP请求,返回响应。
7、浏览器检查HTTP响应是否为一个重定向(3XX结果状态码)、一个验证请求(401)、错误(4XX、5XX)等等,这些都需要根据具体情况分类处理。
8、浏览器接收HTTP响应并且可能关掉TCP连接,或者是重新建立连接使用新情求,获得新响应。
9、浏览器解码响应,如果响应可以缓存,则存入缓存。
10、浏览器显示HTML页面。
11、浏览器发送请求获取嵌入在HTML中的资源(如CSS、JS、图片、音频、视频等)
12、浏览器发送异步请求。
13、页面全部渲染结束。
从输入URL到渲染出整个页面的过程包括三个部分:
1、DNS解析URL的过程
2、浏览器发送请求与服务器交互的过程
3、浏览器对接收到的html页面渲染的过程
一、DNS解析URL的过程
DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS解析就是将域名翻译成IP地址的过程。一个域名对应一个IP,但是一个IP可以对应多个域名
具体过程:
1)浏览器缓存:浏览器会按照一定的频率 缓存DNS记录
2)操作系统缓存:如果浏览器缓存中找不到需要的DNS记录,就会取操作系统中找
3)路由缓存:路由器也有DNS缓存
4)ISP的DNS服务器:ISP有专门的DNS服务器应对DNS查询请求
5)根服务器:ISP的DNS服务器找不到之后,就要向根服务器发出请求,进行递归查询
二、浏览器与服务器交互过程
1)首先浏览器利用tcp协议通过三次握手与服务器建立连接
http请求包括header和body。header中包括请求的方式(get和post)、请求的协议 (http、https、ftp)、请求的地址ip、缓存cookie。body中有请求的内容。
2)浏览器根据解析到的IP地址和端口号发起http的get请求.
3)服务器接收到http请求之后,开始搜索html页面,并使用http返回响应报文
4)若状态码为200显示响应成功,浏览器接收到返回的html页面之后,开始进行页面的渲染
三、浏览器页面渲染过程
1)浏览器根据深度遍历的方式把html节点遍历成dom 树
2)将css解析成CSS DOM树
3)将dom树和CSS DOM树构造成render树
4)JS根据得到的render树 计算所有节点在屏幕中的位置,进行布局(回流)
5)遍历render树并调用硬件API绘制所有节点(重绘)
补充: 构造render渲染树的过程
HTML页面渲染及优化详解:https://www.jianshu.com/p/803679c3827c
前端性能优化可以分为三个level:静态资源优化、接口访问优化、页面渲染速度优化
一、静态资源优化
这个level,主要是减少静态资源的加载时间,主要包括html、css、js和图片文件,静态资源的加载时间是前端性能最大的瓶颈(特别是图片),现如今优化的手段也很丰富,以下简要列举几种常用的方法
二、接口访问优化
如果第一个level做得好,可以保证静态资源以一个较快的速度加载出来,然而,此时情况并没有完美,依然还存在两个明显的问题:
1、静态资源加载完成了,页面依然还在转菊花,用户依然还在等待。现如今web应用已经走过完全由php和jsp等后端脚本语言渲染界面的时代,ajax异步加载数据的方式已经成为主流,各种前端的mvc框架层出不穷,先加载静态资源,在执行js中的ajax请求到后台请求数据,重新渲染界面已经是一种通行的方案,这样便出现了静态资源加载完成,页面可见,然而用户还需要等待请求数据的进度条的情况(特别是接口访问速度慢的时候。
2、用户点击任意一个按钮,进度条加载了半天,也没有响应。很多复杂的功能需要并行或者串行的请求很多接口才能完成,前端的网络状况稍微差一点,给与用户的体验都极差。
以上两个问题在网络情况优异,接口请求速度快的情况下都不是问题,然而终端如果是一个手机,常常连wifi都不能保证,3g/4g的网络你能期待它有多快,所以优化的潜力是巨大的
首屏直出、同构
对于上述的问题一,如果页面的初始化数据,在后端完成渲染,其它的用户交互使用ajax的方式完成,也就是传统意义上的首屏直出,就可以得到很好的解决
这种介于完全后端渲染和完全ajax渲染的方式是一个不错的思路,但是在node出现之前,很多人宁愿容忍首屏加载的菊花,也不愿意使用,为什么?因为前端和后端要维护两套模板,令人抓狂
node出来之后,前后端都都可以使用js语言,前后端同构(前端和后台公用模板代码)使得首屏直出重新拥有了生存的土壤,所以同构直出现在常常相提并论,形同一个成语
react在同构直出方面会做得比较出众!
接口合并
一个交互需要请求多个并行或串行接口实属正常,前端使用3g/4g等弱网络也着实是不可抗因素,所以最好的办法就是通过接口合并的方式来提高接口访问速度
后台提供的接口有其既有粒度,强行合并不合时宜,提供一个新的合并的接口也缺乏机动性(前端发现一个新的合并需求,就要求后端提供一个接口,后端有开发工作量不说,还得没完没了的发版)
如果把接口合并的主动权交给前端,那情况将会好很多,前端是最接近战火的地方,最知道应该如何组合接口。基于代理服务的接口合并方案应运而生。
三、页面渲染速度优化
在页面不复杂、dom层次不深的情况下,完成以上两个level,就已经足够了。然而在复杂的页面上,却还有很大的优化空间,页面渲染速度的优化很大的程度上依托于程序员的个人编程素质,下面简要列举几点:
另外,新晋前端框架 vue、react,虚拟dom的渲染方案,在内存中进行 dom diff 比较,做到最小化的操作真实的 dom (操作真实的 dom 常常会成为性能瓶颈),能极大的提高渲染速度。
使用一些页面性能分析工具给自己的页面跑分,可以帮助养成良好的编程习惯、提升编程素质,例如:WebPagetest、Yslow
具体操作
1、CSS精灵
CSS Sprites在国内很多人叫CSS精灵,是一种网页图片应用处理方式。它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去,这样一来,当访问该页面时,载入的图片就不会像以前那样一幅一幅地慢慢显示出来了。对于当前网络流行的速度而言,不高于200KB的单张图片的所需载入时间基本是差不多的,所以无需顾忌这个问题。
2、代码压缩
(1)将table改为div布局
尽量将table标签布局HTML重构div布局,可以节约至少40%的代码量。由于div代码少于table布局的HTML网页,所以搜索引擎索引权重也优于table布局的HTML网页。
(2)缩减精简div、span、ul、li等系列标签
布局DIV+CSS网页时候,有时候可以节约一些DIV布局代码,减少代码量。
(3)删除多余空格
删除多余空格换行,可以有效地压缩HTML代码占用字节,一般在开发完成后可以对HTML中代码进行删除换行和空格内容。
(4)表格类型布局时候适当使用table替代div布局
如果是本身是表格数据列表排版,我们最好选择table,因为表格布局使用table优于div布局,使用table布局却比div布局节约HTML标签代码和节约CSS样式。
(5)网页GZIP压缩
自己的服务器推荐设置网页Gzip压缩功能。
3、高质量的JS代码肯定能省很多事,封装JS以及重复调用方法能够减少很多操作。
4、减少对DOM的操作
(1)创建临时父元素。
(2)创建子元素,并添加内容,设置属性。
(3)把子元素加入到临时父元素中。
(4)把临时父元素添加到DOM树。
或:(1)找到要添加位置的元素。
(2)改变该元素内容为需要的HTML。
5、使用JSON格式来进行数据交换
原理:JSON是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式。同时,JSON是JavaScript原生格式,这意味着在 JavaScript 中处理 JSON数据不需要任何特殊的 API 或工具包。
7、使用CDN加速(内容分发网络)
CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。
一、减少请求资源大小或者次数
1、尽量和并和压缩css和js文件。(将css文件和并为一个。将js合并为一个)
原因:主要是为了减少http请求次数以及减少请求资源的大小
打包工具:
webpack
gulp
grunt
. ....
2、尽量所使用的字体图标或者SVG图标来代替传统png图
因为字体图标或者SVG是矢量图,代码编写出来的,方大不会变形,而且渲染速度快
3、采用图片的懒加载(延迟加载)
目的为了,减少页面第一次加载过程中http的请求次数
具体步骤:
1、页面开始加载时不去发送http请求,而是放置一张占位图
2、当页面加载完时,并且图片在可视区域再去请求加载图片信息
4、能用css做的效果,不要用js做,能用原生js做的,不要轻易去使用第三方插件。
避免引入第三方大量的库。而自己却只是用里面的一个小功能
6、减少对cookie的使用(最主要的就是减少本地cookie存储内容的大小),因为客户端操作cookie的时候,这些信息总是在客户端和服务端传递。如果上设置不当,每次发送
一个请求将会携带cookie
7、前端与后端进行数据交互时,对于多项数据尽可能基于json格式来进行传送。相对于使用xml
来说传输有这个优势
目的:是数据处理方便,资源偏小
8、前端与后端协商,合理使用keep-alive
9、前端与服务器协商,使用响应资源的压缩
10、避免使用iframe
不仅不好管控样式,而且相当于在本页面又嵌套其他页面,消耗性能会更大。因为还回去加载这个嵌套页面的资源
11、在基于ajax的get请求进行数据交互的时候,根据需求可以让其产生缓存(注意:这个
缓存不是我们常看到的304状态码,去浏览器本地取数据),这样在下一次从相同地址获取是数据
时,取得就是上一次缓存的数据。(注意:很少使用,一般都会清空。根据需求来做)
二、代码优化相关
1、在js中尽量减少闭包的使用
原因:使用闭包后,闭包所在的上下文不会被释放
2、减少对DOM操作,主要是减少DOM的重绘与回流(重排)
关于重排(回流)的分离读写:如果需要设置多个样式,把设置样式全放在一起设置,不要一条一条的设置。使用文档碎片或者字符串拼接做数据绑定(DOM的动态创建)
3、在js中避免嵌套循环和"死循环"(一旦遇到死循环,浏览器就会直接卡掉)
4、把css放在body上,把js放在body下面
让其先加载css(注意:这里关于优化没有多大关系)
5、减少css表达式的使用
6、css选择器解析规则所示从右往左解析的。减少元素标签作为对后一个选择对象
7、尽量将一个动画元素单独设置为一个图层(避免重绘或者回流的大小)
注意:图层不要过多设置,否则不但效果没有达到反而更差了
8、在js封装过程中,尽量做到低耦合高内聚。减少页面的冗余代码
9、css中设置定位后,最好使用z-index改变盒子的层级,让盒子不在相同的平面上
10、css导入的时候尽量减少@import导入式,因为@import是同步操作,只有把对应的样式导入后,才会继续向下加兹安,而link是异步的操作
11、使用window.requestAnimationFrame(js的帧动画)代替传统的定时器动画
如果想使用每隔一段时间执行动画,应该避免使用setInterval,尽量使用setTimeout
代替setInterval定时器。因为setInterval定时器存在弊端:可能造成两个动画间隔时间
缩短
12、尽量减少使用递归。避免死递归
解决:建议使用尾递归
13、基于script标签下载js文件时,可以使用defer或者async来异步加载
14、在事件绑定中,尽可能使用事件委托,减少循环给DOM元素绑定事件处理函数。
15、在js封装过程中,尽量做到低耦合高内聚。减少页面的冗余代码
16、减少Flash的使用
三、存储
1、结合后端,利用浏览器的缓存技术,做一些缓存(让后端返回304,告诉浏览器去本地拉取数据)。(注意:也有弊端)可以让一些不太会改变的静态资源做缓存。比如:一些图片,js,cs
2、利用h5的新特性(localStorage、sessionStorage)做一些简单数据的存储,
避免向后台请求数据或者说在离线状态下做一些数据展示。
四、其他优化
1、避免使用iframe不仅不好管控样式,而且相当于在本页面又嵌套其他页面,消耗性能会更大。因为还回去加载这个嵌套页面的资源
2、页面中的是数据获取采用异步编程和延迟分批加载,使用异步加载是数据主要是为了避免浏览器失去响应。如果你使用同步,加载数据很大并且很慢
那么,页面会在一段时间内处于阻塞状态。目的:为了解决请求数据不耽搁渲染,提高页面的
渲染效率。解决方法:需要动态绑定的是数据区域先隐藏,等数据返回并且绑定后在让其显示
延迟分批加载类似图片懒加载。减少第一次页面加载时候的http请求次数
3、页面中出现音视频标签,我们不让页面加载的时候去加载这些资源(否则第一次加载会很慢)
解决方法:只需要将音视频的preload=none即可。
目的:为了等待页面加载完成时,并且音视频要播放的时候去加兹安音视频资源
4、尽量将一个动画元素单独设置为一个图层(避免重绘或者回流的大小)
注意:图层不要过多设置,否则不但效果没有达到反而更差了
当对一个文档进行布局(lay out)的时候,浏览器的渲染引擎会根据标准之一的 CSS 基础框盒模型(CSS basic box model),将所有元素表示为一个个矩形的盒子(box)。每个盒子由四个部分(或称区域)组成,其效用由它们各自的边界(Edge)所定义。如图,与盒子的四个组成区域相对应,每个盒子有四个边界:内容边界 Content edge、内边距边界 Padding Edge、边框边界 Border Edge、外边框边界 Margin Edge。