前端点滴(网络协议/HTML/前端优化/浏览器)

网络协议/HTML/前端优化/浏览器

IOS七层模型

在这里插入图片描述
从地址栏里输入一个URL,到这个页面被渲染出来,中间会发生什么?

输入url后,首先需要找到这个url域名的服务器ip,为了寻找这个ip,浏览器首先会寻找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存-》系统缓存-》路由器缓存,缓存中没有则查找系统的hosts文件中是否有记录,如果没有则查询DNS服务器,得到服务器的ip地址后,浏览器根据这个ip以及相应的端口号,构造一个http请求,这个请求报文会包括这次请求的信息,主要是请求方法,请求说明和请求附带的数据,并将这个http请求封装在一个tcp包中,这个tcp包会依次经过传输层,网络层,数据链路层,物理层到达服务器,服务器解析这个请求来作出响应,返回相应的html给浏览器,因为html是一个树形结构,浏览器根据这个html来构建DOM树,在dom树的构建过程中如果遇到JS脚本和外部JS连接,则会停止构建DOM树来执行和下载相应的代码,这会造成阻塞,这就是为什么推荐JS代码应该放在html代码的后面,之后根据外部样式,内部样式,内联样式构建一个CSS对象模型树CSSOM树,构建完成后和DOM树合并为渲染树,这里主要做的是排除非视觉节点,比如script,meta标签和排除display为none的节点,之后进行布局,布局主要是确定各个元素的位置和尺寸,之后是渲染页面,因为html文件中会含有图片,视频,音频等资源,在解析DOM的过程中,遇到这些都会进行并行下载,浏览器对每个域的并行下载数量有一定的限制,一般是4-6个,当然在这些所有的请求中我们还需要关注的就是缓存,缓存一般通过Cache-Control、Last-Modify、Expires等首部字段控制。 Cache-Control和Expires的区别在于Cache-Control使用相对时间,Expires使用的是基于服务器 端的绝对时间,因为存在时差问题,一般采用Cache-Control,在请求这些有设置了缓存的数据时,会先 查看是否过期,如果没有过期则直接使用本地缓存,过期则请求并在服务器校验文件是否修改,如果上一次 响应设置了ETag值会在这次请求的时候作为If-None-Match的值交给服务器校验,如果一致,继续校验 Last-Modified,没有设置ETag则直接验证Last-Modified,再决定是否返回304。
过程简单来说就是:

  1. DNS解析
  2. TCP连接
  3. 发送HTTP请求
  4. 服务器处理请求并返回HTTP报文
  5. 浏览器解析渲染页面
  6. 连接结束

下面会依次讲到。。。。

网络协议

一、 HTTP与HTTPS协议

(1)http与https概述

http: 超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
https: 是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
https协议的主要作用是:建立一个信息安全通道,来确保数组的传输,确保网站的真实性。

(2)http与https区别

(1)传输的安全性不同。http是明文传输,https设置了SSL协议(加密版的http)。
(2)链接方式不同,端口号也不同。http端口号80,https端口号443。
(3)链接状态不同。http无状态链接,https由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http更加安全。
(4)工作原理不同。http是基于TCP三次握手原理,https是基于SSL+HTTP协议构建的可进行加密传输原理,具体如下:

http协议/TCP协议

在这里插入图片描述

协议流程:
客户端发送syn数据包到服务器,并进入SYN-SENT状态,等待服务器的确认。
服务器收到客户端发来的syn数据包进行验证,正确后发送syn-ack数据包到客户端以确认请求,并进入SYN-RCVD状态。
客户端收到确认后检查服务器发送过来的syn-ack数据包,并发送ack包到服务器中,服务器验证信息如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据。

扩展

(1)SYN攻击
在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了,使用如下命令可以让之现行:#netstat -nap | grep SYN_RECV
(2)http2.0
1.提升访问速度(可以对于,请求资源所需时间更少,访问速度更快,相比http1.0)
2.允许多路复用:多路复用允许同时通过单一的HTTP/2连接发送多重请求-响应信息。改善了:在http1.1中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制(连接数量),超过限制会被阻塞。
3.二进制分帧:HTTP2.0会将所有的传输信息分割为更小的信息或者帧,并对他们进行二进制编码
4.首部压缩
5.服务器端推送

TCP(四次挥手)协议

在这里插入图片描述
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
这里很多人就会奇怪为什么建立链接是三次握手,而断开链接要四次挥手?
这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端(同时发送)。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,所以造成了多一步流程

https协议

在这里插入图片描述
在这里插入图片描述
第一步:客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
第二步:Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
第三步:客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
第四步:客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
第五步:Web服务器利用自己的私钥解密出会话密钥。
第六步:Web服务器利用会话密钥加密与客户端之间的通信。

(3)http请求方式

1、OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送的请求来测试服务器的功能性
2、HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
3、GET
向特定的资源发出访问、查询请求。
4、POST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
5、PUT
向指定资源位置上传其最新内容
6、DELETE
请求服务器删除Request-URL所标识的资源
7、TRACE
回显服务器收到的请求,主要用于测试或诊断
8、CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

详细请浏览:https://www.cnblogs.com/weibanggang/p/9454581.html

扩展

(1)GET与POST区别,点击查看博文
(2)一个图片url访问后直接下载怎样实现?详情可以点击查看

请求的返回头里面,用于浏览器解析的重要参数就是OSS的API文档里面的返回http头,决定用户下载行为的参数。
下载的情况下:
1.x-oss-object-type : Normal
2.x-oss-request-id : 598D5ED34F29D01FE2925F41
3.x-oss-storage-class : Standard
(3)fetch发送2次请求的原因
在这里插入图片描述
这种情况称为预检(Preflighted)的跨域请求
当HTTP请求出现以下两种情况时,浏览器认为是带预检(Preflighted)的跨域请求:
1). 除GET、HEAD和POST(only with application/x-www-form-urlencoded, multipart/form-data, text/plain Content-Type)以外的其他HTTP方法。
2). 请求中出现自定义HTTP头部。
用fetch的post请求的时候,导致fetch 第一次发送了一个Options请求,询问服务器是否支持修改的请求头,如果服务器支持,则在第二次中发送真正的请求。详细点击查看

(4)http请求头信息

协议 说明
Accept 可接受的响应内容类型(Content-Types)。
Accept-Charset 可接受的字符集
Accept-Encoding 可接受的响应内容的编码方式。
Accept-Language 可接受的响应内容语言列表。
Accept-Datetime 可接受的按照时间来表示的响应内容版本
Authorization 用于表示HTTP协议中需要认证资源的认证信息
Cache-Control 用来指定当前的请求/回复中的,是否使用缓存机制。
Connection 客户端(浏览器)想要优先使用的连接类型
Cookie 由之前服务器通过Set-Cookie(见下文)设置的一个HTTP协议Cookie
Content-Length 以8进制表示的请求体的长度
Content-MD5 请求体的内容的二进制 MD5 散列值(数字签名),以 Base64 编码的结果
Content-Type 请求体的MIME类型 (用于POST和PUT请求中)
Date 发送该消息的日期和时间(以RFC 7231中定义的"HTTP日期"格式来发送)
Expect 表示客户端要求服务器做出特定的行为
From 发起此请求的用户的邮件地址
Host 表示服务器的域名以及服务器所监听的端口号。如果所请求的端口是对应的服务的标准端口(80),则端口号可以省略。
If-Match 仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要用于像 PUT 这样的方法中,仅当从用户上次更新某个资源后,该资源未被修改的情况下,才更新该资源。
If-Modified-Since 允许在对应的资源未被修改的情况下返回304未修改
If-None-Match 允许在对应的内容未被修改的情况下返回304未修改( 304 Not Modified ),参考 超文本传输协议 的实体标记
If-Range 如果该实体未被修改过,则向返回所缺少的那一个或多个部分。否则,返回整个新的实体
If-Unmodified-Since 仅当该实体自某个特定时间以来未被修改的情况下,才发送回应。
Max-Forwards 限制该消息可被代理及网关转发的次数。
Origin 发起一个针对跨域资源共享的请求(该请求要求服务器在响应中加入一个Access-Control-Allow-Origin的消息头,表示访问控制所允许的来源)。
Pragma 与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生。
Proxy-Authorization 用于向代理进行认证的认证信息。
Range 表示请求某个实体的一部分,字节偏移以0开始。
Referer 表示浏览器所访问的前一个页面,可以认为是之前访问页面的链接将浏览器带到了当前页面。Referer其实是Referrer这个单词,但RFC制作标准时给拼错了,后来也就将错就错使用Referer了。
TE 浏览器预期接受的传输时的编码方式:可使用回应协议头Transfer-Encoding中的值(还可以使用"trailers"表示数据传输时的分块方式)用来表示浏览器希望在最后一个大小为0的块之后还接收到一些额外的字段。
User-Agent 浏览器的身份标识字符串
Upgrade 要求服务器升级到一个高版本协议。
Via 告诉服务器,这个请求是由哪些代理发出的。
Warning 一个一般性的警告,表示在实体内容体中可能存在错误。

(5)http请求报文

后台将http首部分为通用首部,请求首部,响应首部,实体首部
通用首部表示一些通用信息,比如date表示报文创建时间,

请求首部就是请求报文中独有的,如cookie,和缓存相关的如if-Modified-Since
响应首部就是响应报文中独有的,如set-cookie,和重定向相关的location

实体首部用来描述实体部分,如allow用来描述可执行的请求方法,content-type描述主题类型,content-Encoding描述主体的编码方式

https://www.cnblogs.com/chenguangliang/p/6708592.html

(6)http返回常见状态码

1 消息
▪ 100 Continue 继续。客户端应继续其请求
▪ 101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
▪ 102 Processing
2 成功
▪ 200 OK 请求成功。一般用于GET与POST请求
▪ 201 Created 已创建。成功请求并创建了新的资源
▪ 202 Accepted 已接受。已经接受请求,但未处理完成
▪ 203 Non-Authoritative Information
▪ 204 No Content
▪ 205 Reset Content
▪ 206 Partial Content
▪ 207 Multi-Status
3 重定向
▪ 300 Multiple Choices
▪ 301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
▪ 302 Move Temporarily 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
▪ 303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
▪ 304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
▪ 305 Use Proxy
▪ 306 Switch Proxy
▪ 307 Temporary Redirect
4 请求错误
▪ 400 Bad Request 客户端请求的语法错误,服务器无法理解
▪ 401 Unauthorized 请求要求用户的身份认证
▪ 402 Payment Required
▪ 403 Forbidden
▪ 404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
▪ 405 Method Not Allowed
▪ 406 Not Acceptable
▪ 407 Proxy Authentication Required
▪ 408 Request Timeout
▪ 409 Conflict
▪ 410 Gone
▪ 411 Length Required
▪ 412 Precondition Failed
▪ 413 Request Entity Too Large
▪ 414 Request-URI Too Long
▪ 415 Unsupported Media Type
▪ 416 Requested Range Not Satisfiable
▪ 417 Expectation Failed
▪ 418 I’m a teapot
▪ 421 Too Many Connections
▪ 422 Unprocessable Entity
▪ 423 Locked
▪ 424 Failed Dependency
▪ 425 Too Early
▪ 426 Upgrade Required
▪ 449 Retry With
▪ 451 Unavailable For Legal Reasons
5 服务器错误
▪ 500 Internal Server Error 服务器内部错误,无法完成请求
▪ 501 Not Implemented 服务器不支持请求的功能,无法完成请求
▪ 502 Bad Gateway
▪ 503 Service Unavailable
▪ 504 Gateway Timeout
▪ 505 HTTP Version Not Supported
▪ 506 Variant Also Negotiates
▪ 507 Insufficient Storage
▪ 509 Bandwidth Limit Exceeded
▪ 510 Not Extended
▪ 600 Unparseable Response Headers

扩展

(1)400状态码的产生原因
前端提交数据的字段名称和字段类型与后台的实体没有保持一致
前端提交到后台的数据应该是json字符串类型,但是前端没有将对象JSON.stringify转化成字符串。
解决方法:对照字段的名称,保持一致性,将obj对象通过JSON.stringify实现序列化

(2)返回码301和302的区别
好文:https://www.simcf.cc/2045.html

二、UDP用户数据报协议

(1)TCP和UDP的区别

特征点 TCP UDP
是否连接 面向连接 面向非连接
传输可靠性 可靠 会丢包,不可靠
应用场景 传输数据量大 传输量小
速度

(1)TCP是面向连接的,udp是无连接的即发送数据前不需要先建立链接。
(2)TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。 并且因为tcp可靠,面向连接,不会丢失数据因此适合大数据量的交换。
(3)TCP是面向字节流,UDP面向报文,并且网络出现拥塞不会使得发送速率降低(因此会出现丢包,对实时的应用比如IP电话和视频会议等)。
(4)TCP只能是1对1的,UDP支持1对1,1对多。
(5)TCP的首部较大为20字节,而UDP只有8字节。
(6)TCP是面向连接的可靠性传输,而UDP是不可靠的。

详细可以查看网络协议 – UDP协议

三、HTML5 WebSocket协议

HTML5 WebSocket:长连接,客户端与服务端可以保持长时间的通信。
详细可以参考:
HTML5 WebSocket
html5-websocket初探

HTML

一、HTML标签(基础)

在这里插入图片描述
详细请点击查看w3schoolhtml参考手册

​行内元素不可以设置宽(width)和高(height),但可以与其他行内元素位于同一行,行内元素内一般不可以包含块级元素。行内元素的高度一般由元素内部的字体大小决定,宽度由内容的长度控制。行内元素有以下特点: ​

  • 每一个行内元素可以和别的行内元素共享一行,相邻的行内元素会排列在同一行里,直到一行排不下了,才会换行。
  • 行内元素的高度、宽度、行高及顶部和底部边距不可设置。
  • 元素的宽度就是它包含的文字或图片的宽度,不可改变。

(1)行内元素列表

  • a 标签可定义锚
  • abbr 表示一个缩写形式
  • acronym 定义只取首字母缩写
  • b 字体加粗
  • bdo 可覆盖默认的文本方向
  • big 大号字体加粗
  • br 换行
  • cite 引用进行定义
  • code 定义计算机代码文本
  • dfn 定义一个定义项目
  • em 定义为强调的内容
  • i 斜体文本效果
  • img 向网页中嵌入一幅图像
  • input 输入框
  • kbd 定义键盘文本
  • label 标签为 input 元素定义标注(标记)
  • q 定义短的引用
  • samp 定义样本文本
  • select 创建单选或多选菜单
  • small 呈现小号字体效果
  • span 组合文档中的行内元素
  • strong 加粗
  • sub 定义下标文本
  • sup 定义上标文本
  • textarea 多行的文本输入控件
  • tt 打字机或者等宽的文本效果
  • var 定义变量

块级元素,该元素呈现“块”状,所以它有自己的宽度和高度,也就是可以自定义width和height,除此之外,块级元素比较霸道,它独自占据一行高度(float浮动除外),一般可以作为其他容器使用,可容纳块级元素和行内元素。块级元素有以下特点:

  • 每个块级元素都是独自占一行。
  • 元素的高度、宽度、行高和边距都是可以设置的。
  • 元素的宽度如果不设置的话,默认为父元素的宽度(父元素宽度100%)。

(2)块元素列表

  • address 联系方式信息。
  • article 文章内容。HTML5
  • aside 伴随内容。 HTML5
  • audio 音频播放。 HTML5
  • blockquote 块引用。
  • canvas 绘制图形。 HTML5
  • dd 定义列表中定义条目描述。
  • div 文档分区。
  • dl 定义列表。
  • fieldset 表单元素分组。
  • figcaption 图文信息组标题。 HTML5
  • figure 图文信息组 (参照 figcaption)。 HTML5
  • footer 区段尾或页尾。 HTML5
  • form 表单。
  • h1,h2,h3,h4,h5 标题级别 1-6。
  • header 区段头或页头。 HTML5
  • hgroup 标题组。 HTML5
  • hr 水平分割线。
  • noscript 不支持脚本或禁用脚本时显示的内容。
  • ol 有序列表。
  • output 表单输出。 HTML5
  • p 行。
  • pre 预格式化文本。
  • section 一个页面区段。 HTML5
  • table 表格。
  • tfoot 表脚注。
  • ul 无序列表。
  • video 视频。 HTML5

行内块元素顾名思义,该元素既有行内元素的特性也有块元素的特性,行内块元素有以下特点:

  • 不自动换行
  • 能够识别宽高
  • 默认排列方式为从左到右

(3)行内块元素列表

  • img 定义图片
  • input 定义输入框

(4)元素类型转换display,float浮动

  • display:none , 定义元素为空脱离文档流(不占空间)
  • display:block ,定义元素为块级元素
  • display : inline ,定义元素为行内元素
  • display:inline-block ,定义元素为行内块级元素。
  • float:left/right , 定义元素浮动。
扩展

(1)iframe、frame、frameset的区别
iframe默认是块元素,其display样式默认值是block
frame应该说即不是块元素也不是行内元素,它虽然有display样式,但其默认值是none
frameset不是块元素也不是行内元素,因为frameset不能出现在body之内,而且也没有display样式.
frameset标签下只能使用frame标签而不能是iframe标签,iframe标签只能使用在非frameset的页面中,但是包含iframe的页面可以显示在frame中.
(2)iframe定义、优缺点
定义:iframe元素会创建包含另一个文档的内联框架
缺点:

  • 会阻塞主页面的onload事件
  • 搜索引擎无法解读这种页面,不利于SEO
  • iframe和主页面共享连接池,而浏览器对相同区域有限制所以会影响性能。

(3)Doctype作用?严格模式与混杂模式如何区分?它们有何意义?
Doctype声明于文档最前面,告诉浏览器以何种方式来渲染页面,这里有两种模式,严格模式和混杂模式。
严格模式的排版和JS 运作模式是 以该浏览器支持的最高标准运行。
混杂模式,向后兼容,模拟老式浏览器,防止浏览器无法兼容页面。

HTML5

在这里插入图片描述

一、HTML5新增的元素

首先html5为了更好的实践web语义化,增加了header,footer,nav,aside,section等语义化标签,在表单方面,为了增强表单,为input增加了color,emial,data ,range等类型,在存储方面,提供了sessionStorage,localStorage,和离线存储,通过这些存储方式方便数据在客户端的存储和获取,在多媒体方面规定了音频和视频元素audio和vedio,另外还有地理定位,canvas画布,拖放,多线程编程的web worker和websocket协议

二、HTML5语义化标签

HTML5语义化标签是指正确的标签包含了正确的内容,结构良好,便于阅读,比如nav表示导航条,类似的还有article、header、footer等等标签。

三、HTML5 input

详细请访问https://www.w3school.com.cn/html5/html_5_form_attributes.asp

四、HTML5 的缓存机制

(1)Cookie、sessionStorage、localStorage的区别

在这里插入图片描述
都是保存在浏览器端、且同源的
区别在于:
1、数据有效期不同。sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
2、cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下
3、存储大小限制也不同。cookie数据不能超过4K,同时因为每次http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
4、作用域不同。sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的
5、web Storage(sessionStorage,localstorage)支持事件通知机制,可以将数据更新的通知发送给监听者
6、web Storage的api接口使用更方便
sessionStorage与localStorage的用法一致:
window.sessionStorage.clear(all);
window.sessionStorage.removeItem(key);
window.sessionStorage.setItem(key, value);
window.sessionStorage.getItem(key)
cookie用法:
$.cookie(key);
$.cookie(key,value);

(2)Cookie

HTTP是一个无状态协议,因此Cookie的最大的作用就是存储sessionId用来唯一标识用户。什么是无状态协议,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息(key-value格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。

简单来说打个比方,我们去银行办理储蓄业务,第一次给你办了张银行卡,里面存放了身份证、密码、手机等个人信息。当你下次再来这个银行时,银行机器能识别你的卡,从而能够直接办理业务。

cookie的运行机制
当用户第一次访问并登陆一个网站的时候,cookie的设置以及发送会经历以下4个步骤:

客户端发送一个请求到服务器 --》 服务器发送一个HttpResponse响应到客户端,其中包含Set-Cookie的头部 --》 客户端保存cookie(sessionId),之后向服务器发送请求时,HttpRequest请求中会包含一个Cookie的头部 --》服务器返回响应数据

细节可以查看https://www.jianshu.com/p/e3226b36c257

node+express环境下cookie-session的使用

http.js

const express = require('express');
const app = express();
const router = require('./http_dealRequest');
const cookieSession = require('cookie-session');    // 用于验证客户信息
app.use(cookieSession({
    name:'sessionID',       // 命名盾牌
    keys:['chenjianer']     // 设置秘钥
}))
app.use(router);
app.use(express.static('public'));
app.engine('html',require('express-art-template'));
app.listen(8080,(err)=>{console.log('请在浏览器中访问127.0.0.1:8080')});

http_dealRequest.js(配置路由跳转)

/*
* 建立路由方法,得到路由对象, 设置各种请求路由,导出路由器
*/
const express = require('express');
const router = express.Router();
const dealData = require('./http_dealData');

router
.get('/',dealData.getall)
.get('/getone',dealData.getone)
.get('/delone',dealData.delone)
.get('/setone',dealData.setone_get)
.post('/setone',dealData.setone_post)
.get('/login',dealData.login_get)  // 导入所需要的登录页面
.post('/login',dealData.login_post)  // 提交表单数据,进行验证

module.exports = router;

http_dealData.js(处理业务逻辑)

const fs = require('fs');
const url = require('url');
const sql = require('./http-sql');
const formidable = require('formidable');
const getall = (req, res) => {
    // 拦截无状态下访问主页
    if (!req.session.session_data) {
        var scr = "<script>alert('请登录后访问');window.location.href = '/login'</script>"
        res.setHeader('content-type', 'text/html;charset=utf-8');
        return res.end(scr);
    }
    sql.select((data) => {
        res.render('./index.html', { data: data })
    })
}
const login_get = (req, res) => {
    res.render('./login.html', {})
}
const login_post = (req, res) => {
    var form = new formidable.IncomingForm();
    form.parse(req, (err, fields) => {
        res.setHeader('content-type', 'text/html;charset=utf-8');
        sql.user2((data_name, data_psw) => {
            if (fields.username == data_name && fields.psw == data_psw) {
                req.session.session_data = fields;
                var scr = "<script>alert('登录成功');window.location.href='/'</script>";
                res.end(scr);
            }
        })
        sql.user2((data_name, data_psw) => {
            if (fields.username != data_name || fields.psw != data_psw) {
                var scr = "<script>alert('登录失败');window.location.href='/login'</script>";
                res.end(scr);
            }
        })
    })
}
module.exports = { getall, getone, setone_get, setone_post, delone, login_get, login_post }

http-sql.js(服务器数据处理(简易版 增、删、改、查))

var mysql = require('mysql');
var connection = mysql.createConnection({
// 自己连接数据库
    host: '...',
    user: '...',
    password: '...',
    database: '...'
})
var user2 = (callback) =>{
    var sql = "select * from users3";
    connection.query(sql, function (err, data) {
        for(i in data){
            callback(data[i].username,data[i].password);
        }
    })
}
module.exports = {where,select,del,update,user2}
扩展

(1)cookie与session的区别
1、存储位置不同
cookie的数据信息存放在客户端浏览器上。
session的数据信息存放在服务器上。
2、存储容量不同
单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie。
对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。
3、存储方式不同
cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据。
session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。
4、隐私策略不同
cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的。
session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。
5、有效期上不同
开发可以通过设置cookie的属性,达到使cookie长期有效的效果。
session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。
6、服务器压力不同
cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。
session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。
7、浏览器支持不同
假如客户端浏览器不支持cookie:
cookie是需要客户端浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效。关于WAP上的应用,常规的cookie就派不上用场了。
运用session需要使用URL地址重写的方式。一切用到session程序的URL都要进行URL地址重写,否则session会话跟踪还会失效。
假如客户端支持cookie:
cookie既能够设为本浏览器窗口以及子窗口内有效,也能够设为一切窗口内有效。
session只能在本窗口以及子窗口内有效。
8、跨域支持上不同
cookie支持跨域名访问。
session不支持跨域名访问。

(3)sessionStorage

作为html5中Web Storage的一种存储方式,localStorage和sessionStorage一样都是用来存储客户端临时信息的对象。

W3c上给的介绍是这两者区别在于localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。而sessionStorage存储的数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。个人的理解是你在打开一个页面时记录sessionStorage,当你把页面或者浏览器关闭时session中的数据即销毁。没了

sessionStorage的使用
index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <input type="button" value="Login" onclick="submit()" />  
        <input type="text" name="text" id="text" />  
        <input type="button" value="show" onclick="show()" />  
        <a href="33.html" target="_blank">33.html</a>
</body>
<script>
            function submit() {  
                var str = document.getElementById("text").value.trim();  
                setInfo(str);  
                document.getElementById("text").value = "";  
            }  
            //储存数据  
            function setInfo(name) {  
                var storage = window.sessionStorage;  
                storage.setItem('name', name);  
            }  
            //显示数据  
            function show() {  
               var storage = window.sessionStorage;  
               var str = "your name is " + storage.getItem("name");  
               document.getElementById("text").value = str;  
            }  
         </script>  
</html>

先点击show按钮,在文本框出现的是“your name is null”,之后只需在文本框中输入数据再点击login按钮就能把数据存储到sessionStorage。如图
在这里插入图片描述
现在点击show 文本框就显示“your name is xiaoming”。

然后再创建一个33.html,代码:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script>  
        var str = window.sessionStorage;  
        alert(str.getItem("name"));  
    </script>  
</head>
<body>
</body>
</html>

最后只要点击index.html的33.html跳转到该页面就能发现sessionstorage内数据是共享的。

(4)localStorage

W3c上给的介绍是这两者区别在于localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

localStorage的使用
用法类似于sessionStorage的使用

扩展----浏览器强缓存、协商缓存篇 (重点)

浏览器请求流程图

在浏览器第一次发起请求时,本地无缓存,向web服务器发送请求,服务器起端响应请求,浏览器端缓存。过程如下:
在这里插入图片描述
浏览器后续再次进行请求时:
在这里插入图片描述
浏览器缓存是浏览器在本地磁盘对用户最近请求过的文档进行存储,当访问者再次访问同一页面时,浏览器就可以直接从本地磁盘加载文档。
所以根据上面的特点,浏览器缓存有下面的优点:

  • 减少冗余的数据传输
  • 减少服务器负担
  • 加快客户端加载网页的速度

浏览器缓存是Web性能优化的重要方式

由于浏览器缓存加快客户端加载网页的速度
后台都没来得及打开,返回码就看不到了,太快了, 电脑卡? >-<
算了用上面的express启动一个服务

http.js

const express = require('express');
const app = express();
const router = require('./http_dealRequest');
const cookieSession = require('cookie-session');    // 用于验证客户信息
app.use(cookieSession({
    name:'sessionID',       // 命名盾牌
    keys:['chenjianer']     // 设置秘钥
}))
app.use(router);
app.use(express.static('public'));
app.engine('html',require('express-art-template'));
app.listen(8080,(err)=>{console.log('请在浏览器中访问127.0.0.1:8080')});

启动终端输入:node http.js

看看第一次访问,返回码
在这里插入图片描述
在这里插入图片描述
第二次访问,返回码
在这里插入图片描述
在这里插入图片描述
返回码为304原因:
在第一次请求服务器的时候在获取资源之后是会先把该资源缓存在本地的,同时服务器response返回了一个响应头ETag,ETag全称Entity Tag,用来标识一个资源。在具体的实现中,ETag可以是资源的hash值,也可以是一个内部维护的版本号。但不管怎样,ETag应该能反映出资源内容的变化,这是Http缓存可以正常工作的基础。服务器数据使用上述返回的ETag来表示,只要数据这个资源不变,这个Etag就不会变。

/*************************中间过程未修改数据

客户端第二次请求服务器的时候,利用请求头If-None-Match来告诉服务器自己已经有个ETag为…的资源。如果服务器上的资源没有变化,也就是说服务器上的资源的ETag也是…的话,服务器就不会再返回该资源的内容,而是返回一个304的响应,告诉浏览器该资源没有变化,缓存有效,浏览器将直接调用本地缓存。

强缓存与协商缓存(重点)
强缓存相关字段有expires,cache-control。如果cache-control与expires同时存在的话,cache-control的优先级高于expires。
协商缓存相关字段有Last-Modified/If-Modified-Since,Etag/If-None-Match
上图好像没有提到强缓存的相关字段
ctrl+F5强制刷新页面,再次观察后台显示
在这里插入图片描述
缓存三大策略

一、缓存存储策略
对于 Cache-Control 头里的 Public、Private、no-cache、max-age 、no-store 他们都是用来指明响应内容是否可以被客户端存储的,其中前4个都会缓存文件数据(关于 no-cache 应理解为“不建议使用本地缓存”,其仍然会缓存数据到本地),后者 no-store 则不会在客户端缓存任何响应数据。另关于 no-cache 和 max-age 有点特别----称多重缓存头

而通过 Cache-Control:Public/Private等常规模式设置。我们可以将 Http 响应数据存储到本地,但此时并不意味着后续浏览器会直接从缓存中读取数据并使用,因为它无法确定本地缓存的数据是否可用(可能已经失效),还必须借助一套鉴别机制来确认才行。这就是“缓存过期策略”。

二、缓存过期策略

客户端用来确认存储在本地的缓存数据是否已过期,进而决定是否要发请求到服务端获取数据
这个策略的作用也只有一个,那就是决定客户端是否可直接从本地缓存数据中加载数据并展示(否则就发请求到服务端获取)

上面我们阐述了数据缓存到了本地后还需要经过判断才能使用,那么浏览器通过什么条件来判断呢? 答案是:Expires,Expires 指名了缓存数据有效的绝对时间(注意是绝对时间),告诉客户端到了这个时间点(比照客户端时间点)后本地缓存就作废了,在这个时间点内客户端可以认为缓存数据有效,可直接从缓存中加载展示。

不过 Http 缓存头设计并没有想象的那么规矩,像上面提到的 Cache-Control(这个头是在Http1.1里加进来的)头里的 no-cache 和 max-age 就是特例,它们既包含缓存存储策略也包含缓存过期策略,以 max-age 为例,它实际上相当于:

Cache-Control:public/private
Expires:当前客户端时间 + maxAge 。

而Cache-Control:no-cache === Cache-Control:max-age=0

但是要注意的是如果cache-control与expires同时存在的话,cache-control的优先级高于expires。

三、缓存对比策略

将缓存在客户端的数据标识发往服务端,服务端通过标识来判断客户端 缓存数据是否仍有效,进而决定是否要重发数据。

客户端检测到数据过期或浏览器刷新后,往往会重新发起一个 http 请求到服务器,服务器此时并不急于返回数据,而是看请求头有没有带标识( If-Modified-Since、If-None-Match)过来,如果判断标识仍然有效,则返回304告诉客户端取本地缓存数据来用即可(这里要注意的是你必须要在首次响应时输出相应的头信息(Last-Modified、ETag)到服务器)服务器会优先验证ETag。所以说上面所说的本地缓存数据即使被认为过期,并不等于数据从此就没用了的道理了。
所以最终说明第一次访问服务器Cache-Control:no-cache,返回码200。第二次访问,返回304的原因,就是因为Cache-Control:no-cache可缓存,且缓存失效重新发送http请求,但是又比对正确的结果,返回304

缓存策略 缓存策略值 得出结果 备注
缓存存储策略 Cache-Control:public/private 响应的数据会被缓存到客户端 由Cache-Control:no-cache得来
缓存过期策略 Expires:当前客户端时间 马上过期第二次访问服务器会重新发送http请求 由Cache-Control:no-cache得来
缓存对比策略 ETag: W/“fa0-jPg1f/MBYYjzWNnM698oTpLVpeo” 比对成功 浏览器会携带Etag值到服务器中进行比较,如果对比相同返回状态码304,服务器提示浏览器到本地缓存中加载数据,否则返回200服务器响应数据

再来说说常规头,比如Cache-Control :public
下面是一个请求头

HTTP/1.1 200 OK
Cache-Control: public
Content-Type: image/png
Last-Modified: Tue, 08 Nov 2016 06:59:00 GMT
Accept-Ranges: bytes
Date: Thu, 10 Nov 2016 02:48:50 GMT
Content-Length: 3534

其中涉及缓存的因素有

Cache-Control: public
Last-Modified: Tue, 08 Nov 2016 06:59:00 GMT

但是缺少缓存过期策略的因素expires
在这里插入图片描述
再看看 Chrome 浏览器下抓包:
在这里插入图片描述
实测发现:多次页面刷新,发现只发送了一次http请求,剩下的都是直接取了本地缓存,也就是说存在某种机制使得缓存没有过期,造成客户端不能重新发送http请求,而是直接从本地缓存中获取数据,后又由于对比失败返回状态码200,经过对比发现:
在这里插入图片描述
原来,在没有提供任何浏览器缓存过期策略的情况下,浏览器遵循一个启发式缓存过期策略:

根据响应头中2个时间字段 Date 和 Last-Modified 之间的时间差值,取其值的10%作为缓存时间周期配置expires。

所以,得出结论

缓存策略 缓存策略值 得出结果 备注
缓存存储策略 Cache-Control:public 响应的数据会被缓存到客户端 由Cache-Control:public得来
缓存过期策略 Expires:当前客户端时间+(Date - Last-Modified)*10% 怎么算也不可能过期 由启发式缓存过期策略:响应头中2个时间字段 Date 和 Last-Modified 之间的时间差值,取其值的10%作为缓存时间周期配置expires得来
缓存对比策略 Last-Modified: Tue, 08 Nov 2016 06:59:00 GMT 比对失败 浏览器会携带Last-Modified/Etag值到服务器中进行比较,如果对比相同返回状态码304,服务器提示浏览器到本地缓存中加载数据,否则返回200服务器响应数据

总结:
协商缓存就是将资源一些相关信息返回服务器,让服务器判断浏览器是否能直接使用本地缓存,整个过程至少与服务器通信一次

第一次访问,状态码200 第二次访问,返回码200 第二次访问,返回码304
缓存存储策略 有缓存 有缓存
缓存过期策略 缓存过期,重新发送http请求 缓存过期,重新发送http请求
缓存对比策略 对比失败,不可用,刷新 对比成功,可用

强缓存直接使用本地的缓存,不用跟服务器进行通信

第一次访问,状态码200 第二次访问,返回码200
缓存存储策略 有缓存
缓存过期策略 缓存没过期,不发送http请求,直接从本地缓存取
缓存对比策略 对比失败,不可用,刷新

五、audio和vedio的使用

首先了解小程序开发
https://www.jianshu.com/p/df3ff0e284a6
https://blog.csdn.net/qq_43043859/article/details/90513170
由于Chrome等各类主流浏览器均设置了节流模式所以audio和vedio中的atuoplay失效,MicrosoftEdge、360浏览器支持autoplay
所以主要还是用于H5开发

六、canvas画布的使用

推荐
https://blog.csdn.net/u012468376/article/details/73350998
https://blog.csdn.net/paulxin2008/article/details/20940255

七、drag拖动特效

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style type="text/css">
        #div1 {
            width: 198px;
            height: 66px;
            padding: 10px;
            border: 1px solid #aaaaaa;
        }
    </style>
    <script type="text/javascript">
        function allowDrop(ev) {
            ev.preventDefault();
        }
        function drag(ev) {
            ev.dataTransfer.setData("Text", ev.target.id);
        }
        function drop(ev) {
            ev.preventDefault();
            var data = ev.dataTransfer.getData("Text");
            ev.target.appendChild(document.getElementById(data));
        }
    </script>
</head>
<body>
    <p>请把 123 拖放到矩形中:</p>
    <div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <br />
    <p id="drag1" draggable="true" ondragstart="drag(event)" >123</p>
</body>
</html>

在这里插入图片描述
draggable:设置成是否允许被拖动
dragstart:事件主体是被拖放元素,在开始拖放被拖放元素时触发,。
darg:事件主体是被拖放元素,在正在拖放被拖放元素时触发。
dragenter:事件主体是目标元素,在被拖放元素进入某元素时触发。
dragover:事件主体是目标元素,在被拖放在某元素内移动时触发。
dragleave:事件主体是目标元素,在被拖放元素移出目标元素是触发。
drop:事件主体是目标元素,在目标元素完全接受被拖放元素时触发。
dragend:事件主体是被拖放元素,在整个拖放操作结束时触发

八、Web Worker多线程数据的交互

在HTML页面中,如果在执行脚本时,页面的状态是不可相应的,直到脚本执行完成后,页面才变成可相应。web worker是运行在后台的js,独立于其他脚本,不会影响页面你的性能。并且通过postMessage将结果回传到主线程。这样在进行复杂操作的时候,就不会阻塞主线程了。

如何创建web worker:

  • 检测浏览器对于web worker的支持性 (Chrome浏览器不支持web worker)
  • 创建web worker文件(js,回传函数等)
  • 创建web worker对象

业务如下,随机生成一个整数数组,然后将该整数数组传入线程,挑选出数组中可以被3整除的数字,然后显示在页面的表格中,主页面代码如下:

主线程index.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
	<script type="text/javascript" src="jquery-3.3.1.js"></script>
	<!-- 业务如下,随机生成一个整数数组,然后将该整数数组传入线程,挑选出数组中可以被3整除的数字,然后显示在页面的表格中,主页面代码如下: -->
	<script>
		$(function () {
			var arr = new Array(100);
			for (var i = 0; i < arr.length; i++) {
				arr[i] = parseInt(Math.random() * 100);
			};
			var worker = new Worker("myWorker.js");
			worker.postMessage(JSON.stringify(arr));
			worker.addEventListener("message", function (event) {
				if (event.data != "") {
					var array = JSON.parse(event.data);
					var row, col;
					for (var index = 0; index < array.length; index++) {
						row = parseInt(index / 10);
						col = index % 10;
						if (col == 0) {
							$("<tr>").appendTo("tbody");
						}
						$("<td>").text(array[row * 10 + col]).appendTo("tbody tr:last");
					}
				}
			}, false)
		})
	</script>
</head>
<body>
	<table>
		<caption>从随机生成的数字中抽取3的倍数并显示</caption>
		<tbody></tbody>
	</table>
</body>
</html>

子线程myWorker.js

self.addEventListener("message", function (event) {
    var data = JSON.parse(event.data);
    var returnArray = new Array();
    var temp;
    for (var index = 0; index < data.length; index++) {
        if ((temp = data[index]) % 3 == 0) {
            returnArray.push(temp);
        }
    }
    self.postMessage(JSON.stringify(returnArray));
}, false);

在Chrome浏览器下运行,不支持多线层编程
在这里插入图片描述
在MicrosoftEdge下运行,支持多线层编写
在这里插入图片描述

一、线程嵌套

线程中可以嵌套子线程,这样我们可以把一个较大的后台线程切分成几个子线程,在每个子线程中各自完成相对独立的一部分工作。称之为单层嵌套

二、单层嵌套

上面的主线程可以继续拆分成各个单层,来完成更大的工程

修改主线程index.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
	<script type="text/javascript" src="jquery-3.3.1.js"></script>
	<!-- 业务如下,随机生成一个整数数组,然后将该整数数组传入线程,挑选出数组中可以被3整除的数字,然后显示在页面的表格中,主页面代码如下: -->
	<script>
		$(function () {
			var worker = new Worker("myWorker.js");
			worker.postMessage("");
			worker.addEventListener("message", function (event) {
				if (event.data != "") {
					var array = JSON.parse(event.data);
					var row, col;
					for (var index = 0; index < array.length; index++) {
						row = parseInt(index / 10);
						col = index % 10;
						if (col == 0) {
							$("<tr>").appendTo("tbody");
						}
						$("<td>").text(array[row * 10 + col]).appendTo("tbody tr:last");
					}
				}
			}, false)
		})
	</script>
</head>
<body>
	<table>
		<caption>从随机生成的数字中抽取3的倍数并显示</caption>
		<tbody></tbody>
	</table>
</body>
</html>

二级线程myWorker.js

self.addEventListener("message", function (event) {
    var arr = new Array(100);
    for (var i = 0; i < arr.length; i++) {
        arr[i] = parseInt(Math.random() * 100);
    };
    var worker = new Worker("myWorker2.js")
    worker.postMessage(JSON.stringify(arr));
    worker.addEventListener("message", function (event1) {
        self.postMessage(event1.data);   // 返回主线程挑选结果
    }, false)
}, false);

三级线程myWorker2.js

self.addEventListener("message", function (event) {
    var data = JSON.parse(event.data);
    var returnArray = new Array();
    var temp;
    for (var index = 0; index < data.length; index++) {
        if ((temp = data[index]) % 3 == 0) {
            returnArray.push(temp);
        }
    }
    self.postMessage(JSON.stringify(returnArray)); // 将返回结果返回带上一级层级
    self.close();  // 关闭子线程
}, false)

在MicrosoftEdge下运行,支持多线层编写
在这里插入图片描述
在Chrome浏览器下运行,不支持多线层编程
在这里插入图片描述
详细还可以参考,点击查看

扩展

addEventListener(event, function, useCapture)

其中,event指定事件名;function指定要事件触发时执行的函数;useCapture指定事件是否在捕获或冒泡阶段执行。

前端优化

https://blog.csdn.net/Errrl/article/details/103721482
降低请求量:合并资源,减少HTTP 请求数,minify / gzip 压缩,webP,lazyLoad,预加载。
加快请求速度:预解析DNS,减少域名数,并行加载,CDN 分发。
缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存localStorage。
渲染:JS/CSS优化,加载顺序,服务端渲染,pipeline。

减少HTTP 请求数

  • 尽量减少页面的HTTP请求,可以提高页面载入速度。
  • 减少页面中的元素网页中的的图片、form、flash等等元素都会发出HTTP请求,尽可能的减少页面中非必要的元素,可以减少HTTP请求的次数。
  • 图片地图(Image Maps也就是图像热点,图像地图就是把一张图片分成若干区域,每个区域指向不同的URL地址,这些区域也称为热点。ImageMaps只适用于连续的图标。
  • CSS Sprites(CSS精灵)图片是增加HTTP请求的最大可能者,把全站的图标都放在一个图像文件中,然后用CSS的background-image和background-position属性定位来显示其中的一小部分。这种方法把CSS写到HMTL文件里,而不采用外部调用,与Div+CSS中「表现与内容分离、把CSS都立出来」相悖,缺点就是不利于SEO;当然,从整体上减少HTTP请求、提高页面载入速度,是有利于SEO的。
  • JS文件和CSS文件只有一个。合并脚本和CSS文件,可以减少了HTTP请求。有的人喜欢把CSS分成结构清晰的几个部分,比如base.css、header.css、mianbody.css、 footer.css这样对页面的维护和修改是比较方便的,但是对加快服务器响应时间就存在问题了。
  • 少用location.reload(),使用location.reload() 会刷新页面,刷新页面时页面所有资源(css,js,img等)会重新请求服务器。建议location.href=“当前页url” 代替location.reload() ,使用location.href 浏览器会读取本地缓存资源。
  • 动态页面静态化。动态网页实际上并不是独立存在于服务器上的网页文件,只有当用户请求时服务器才返回一个完整的网页。用户访问动态页面需要与数据库服务器进行数据交换。

防抖与节流

lazyLoad懒惰加载(节流)
前端工作中,界面和效果正在变得越来越狂拽炫酷,与此同时性能也是不得不提的问题。有些项目,页面长,图片多,内容丰富。像商城页面。如果同步加载时一次性加载完毕,那肯定是要等到花都谢了,loading转的人都崩溃~。今天分享的是Lazyload技术 是一种延迟加载技术。让页面加载速度快到飞起、减轻服务器压力、节约流量、提升用户体验。

实现思路:
页面较长,屏幕的可视区域有限。
不设置页面中img标签的src属性值或者将其指向同一个占位图。
图片的实际地址存在img标签自定义的一个属性中,如:“data-url”。
监听scroll,滚动到某个位置时,动态的将url替换成实际的“data-url”。

html设置:

<head>
    <meta charset="UTF-8">
    <title>Lazyload</title>
    <style type="text/css">
        .mob-wrap li {
            list-style: none;
            width: 100%;
            height: 600px;
        }
    </style>
</head>

<body>
    <ul class="mob-wrap">
        <li>
            <img class="tamp-img" alt="loading" data-src="banner1.gif">
        </li>
        <li>
            <img class="tamp-img" alt="loading" data-src="banner1.jpg">
        </li>
        <li>
            <img class="tamp-img" alt="loading" data-src="banner2.gif">
        </li>
        <li>
            <img class="tamp-img" alt="loading" data-src="banner2.gif">
        </li>
        <li>
            <img class="tamp-img" alt="loading" data-src="banner2.gif">
        </li>
        <li>
            <img class="tamp-img" alt="loading" data-src="banner2.gif">
        </li>
        <li>
            <img class="tamp-img" alt="loading" data-src="banner2.gif">
        </li>
    </ul>
</body>

js:

//节流函数
    _throttle = (fn, delay, least) => {
        var timeout = null,
            startTime = new Date();
        fn();
        return function () {
            var curTime = new Date();
            clearTimeout(timeout);
            if (curTime - startTime >= least) {
                fn();
                startTime = curTime;
            } else {
                timeout = setTimeout(fn, delay);
            }
        }
    }
    function compare() {
        var bodyScrollHeight = document.documentElement.scrollTop;// body滚动高度
        console.log(bodyScrollHeight + "替换src方法")
        var windowHeight = window.innerHeight;// 视窗高度
        var imgs = document.getElementsByClassName('tamp-img');
        for (var i = 0; i < imgs.length; i++) {
            var imgHeight = imgs[i].offsetTop;// 图片距离顶部高度 
            if (imgHeight < windowHeight + bodyScrollHeight - 340) {
                imgs[i].src = imgs[i].getAttribute('data-src');
                imgs[i].className = imgs[i].className.replace('tamp-img', '');
            }
        }
    }
    window.onscroll = _throttle(compare, 350, 600);

preload预加载
https://blog.csdn.net/daxianghaoshuai/article/details/80988054

preload预加载与lazyLoad懒加载区别以及配置
http://baijiahao.baidu.com/s?id=1600329086509656507&wfr=spider&for=pc

浏览器

浏览器对象(BOM对象)

(1)几个很实用的BOM属性对象方法

  1. window对象
    window对象不但充当全局作用域,而且表示浏览器窗口,最常用的属性包括
    window.innerHeight
    window.innerWidth
    window.outerWidth
    window.outerHeight
    可以获取浏览器窗口的内部、外部的宽度和高度。内部宽高是指除去菜单栏、工具栏、边框等占位元素后,用于显示网页的净宽高,外部指的是整体浏览器。
  2. location对象
    表示当前页面的URL信息。例如,一个完整的URL:
    http://www.example.com:8080/path/index.html?a=1&b=2#TOP
    最常用的属性包括
location.protocol; // 'http'
location.host; // 'www.example.com'
location.port; // '8080'
location.pathname; // '/path/index.html'
location.search; // '?a=1&b=2'
location.hash; // 'TOP'

要加载一个新页面,可以调用location.assign()。如果要重新加载当前页面,调用location.reload()方法非常方便。

if (confirm('重新加载当前页' + location.href + '?')) {
    location.reload();
} else {
    location.assign('/'); // 设置一个新的URL地址
}
  1. history对象
    最常用的属性包括
    history.go() – 前进或后退指定的页面数 history.go(num);
    history.back() – 后退一页
    history.forward() – 前进一页

history对象保存了浏览器的历史记录,JavaScript可以调用history对象的back()或forward(),相当于用户点击了浏览器的“后退”或“前进”按钮。这个对象属于历史遗留对象,对于现代Web页面来说,由于大量使用AJAX和页面交互,简单粗暴地调用history.back()可能会让用户感到非常愤怒。新手开始设计Web页面时喜欢在登录页登录成功时调用history.back(),试图回到登录前的页面。这是一种错误的方法。任何情况,你都不应该使用history这个对象了。

  1. document对象
    表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,document对象就是整个DOM树的根节点。最常用的属性包括
    document.getElementById()
    document.getElementsByTagName()
    document.querySelector()
    document.querySelectorall()
  2. screen对象
    表示整个屏幕的信息,常用的属性有
    screen.width:屏幕宽度,以像素为单位;
    screen.height:屏幕高度,以像素为单位;
    screen.colorDepth:返回颜色位数,如8、16、24。
  3. navigator对象
    表示浏览器的信息,最常用的属性包括
    navigator.appName:浏览器名称;
    navigator.appVersion:浏览器版本;
    navigator.language:浏览器设置的语言;
    navigator.platform:操作系统类型;
    navigator.userAgent:浏览器设定的User-Agent字符串。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章