PS:其中大多数图片是引用自其他优秀作者,本文仅仅作为个人学习的记录,不作为商业用途。
优化页面加载速度
- 优化图像
- 使用cdn
- 减少DNS查找
- 精简js、css代码
- 压缩组件
- 懒加载
- 减少http请求
- 避免重定向
- 删除重复脚本
- 利用浏览器缓存
浏览器渲染过程i
(1)浏览器解析HTML源码,然后创建一个DOM树。
在DOM树中,每一个HTML标签都有一个对应的节点(元素节点),并且每一个文本也都有一个对应的文本节点,DOM树的根节点就是documentElement,对应的是html标签
(2)浏览器解析CSS代码,然后创建一个CSS树。
解析CSS的时候会按照如下顺序来定义优先级(递增):浏览器默认设置<用户设置<外联样式<内联样式<标签样式
(3)根据DOM树和CSSOM来构建一个渲染树(rendertree)。
(4)一些js代码对DOM元素的改变,会导致重流或者重绘。
(4)当渲染树创建完成之后,浏览器就可以根据渲染树直接把页面绘制到屏幕上。
渲染树和DOM树的关系
(1)在DOM树构建的同时,浏览器会构建渲染树。(为了提高用户体验,浏览器并不会等到所有HTML文档加载完成之后才建立渲染树并渲染,而是会在从网络层获取html文档的同时把已经接收到的局部内容先渲染出来)
(2)DOM树完全和html标签一一对应,而渲染树会忽略(即不包含)不需要渲染的元素(如head,样式为display:none的元素等)
(3)渲染树中每一个节点都存储着对应的CSS属性
reflow(重排,回流)和repaint(重绘)
reflow:浏览器要花时间去渲染,当它发现了某个部分发生了变化并且影响了布局,就需要倒回去重新渲染
repaint:如果只是改变了某个元素的背景颜色或文字颜色等,不影响元素周围或内部布局,就只会引起浏览器的repaint,重画其中一部分。
reflow比repaint更花费时间,也就更影响性能,所以在写代码时应尽量避免过多的reflow。
XSS及CSRF攻击防御
XSS攻击全称跨站脚本攻击(Cross Site Scripting) ,是一种常见于 Web 应用中的计算机安全漏洞。恶意攻击者往 Web 页面里嵌入恶意的客户端脚本,当用户浏览此网页时,脚本就会在用户的浏览器上执行,进而达到攻击者的目的。比如获取用户的 Cookie、导航到恶意网站、携带木马等。
防御措施:
1、使用 XSS Filter
针对用户提交的数据进行有效的验证,只接受我们规定的长度或内容的提交,过滤掉其他的输入内容。比如:
表单数据指定值的类型:年龄只能是 int 、name 只能是字母数字等。
过滤或移除特殊的 html 标签:
过滤 js 事件的标签:onclick、onerror、onfocus等。
2、Http Only cookie
许多 XSS 攻击的目的就是为了获取用户的 cookie,将重要的 cookie 标记为 http only,这样的话当浏览器向服务端发起请求时就会带上 cookie 字段,但是在脚本中却不能访问 cookie,这样就避免了 XSS 攻击利用 js 的 document.cookie获取 cookie。
CSRF(Cross-site request forgery)跨站请求伪造, 也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF;
防御措施:
验证 HTTP Referer 字段 ,HTTP Referer字段通常会指向请求网站的url,如果黑客使用CSRF方式,HTTP Referer会指向黑客自己的网站,验证HTTP Referer字段,可以有效避免CSRF攻击。
计算机网络
同源策略
如果两个URL的协议、域名和端口相同的话,则说明这两个URL是同源的。同源策略是浏览器通过的一种安全策略,它用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。简单来说,如果网站A和网站B不同源,那么网站A就不能读取非同源网页B的Cookie、localStorage,也不能接触B网站的DOM。而且A无法向非同源地址发送AJAX请求。同源策略能帮助阻隔恶意文档,减少可能被攻击的媒介。
浏览器允许发起跨域请求,但是跨域请求回来的数据会被浏览器拦截,Web页面无法获取。
cors
CORS跨域资源共享是一个W3C标准,它是一种基于HTTP头的机制,该机制通过允许服务器标示除了它自己以外的其他源,这样浏览器就可以向跨域的服务器发送AJAX请求访问加载资源了。
设置Access-Control-Allow-Origin为你允许跨域的网站
Access-Control-Allow-Methods 为允许的方法
Access-Control-Allow-Credentials 允许客户端携带验证信息
osi7层协议
TCP协议在传输层工作
HTTP在应用层工作
对称加密和非对称加密
对称加密:客户端和服务器只有用一个公钥
非对称加密:客户端和服务端拥有私钥和公钥这样的一对钥匙。私钥不能发送给他人,而公钥可以。
websocket
说明:WebSocket是一种在单个TCP连接上进行全双工通信的协议。
优点:1.全双工协议:服务器可以随时主动向客户端发送数据。
2.较少的控制开销:Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小。
3.对二进制更好地支持
轮询
说明:每隔一段时候,就发出一个询问,了解服务器有没有新的信息。最典型的场景就是聊天室。
缺点:浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
例如:
客户端:啦啦啦,有没有新信息(Request) 服务端:没有(Response) 客户端:啦啦啦,有没有新信息(Request) 服务端:没有。。(Response) 客户端:啦啦啦,有没有新信息(Request) 服务端:你好烦啊,没有啊。。(Response) 客户端:啦啦啦,有没有新消息(Request) 服务端:好啦好啦,有啦给你。(Response)
long poll
说明:采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。
例如:
客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) 服务端:额。。 等待到有消息的时候。。来 给你(Response) 客户端:啦啦啦,有没有新信息,没有的话就等有了才返回给我吧(Request) -loop
缺点:浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
IP协议首部结构
IP协议的首部结构包括20字节的固定头部信息,和40字节的可选字段信息。固定部分包括IP协议版本、首部长度、区分服务、数据总长度、标识、标志、片偏移、生存时间、协议、首部校验和、源地址、目的地址。可变部分是1到40字节不等,增强了数据报的功能但是增加了路由器处理数据的开销。
HTTP
说明:HTTP 是为 Web 浏览器与 Web 服务器之间的通信而设计的,HTTP 是一个基于 TCP/IP 通信协议来传递数据的
特点:
- HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
- HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。 缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
http请求方式
get和post的区别
Get
- 一般用于获取数据
- 基于URL地址传参,所以有个长度限制(一般在8kb),如果超过就会被截掉
- 因为get请求基于问号传参容易被劫持,所以相对不安全
- 会产生不可控的缓存,POST不会
Post
- 一般用于新增数据
- 基于请求传参,理论上没有任何限制(真实项目中会自己做大小限制,防止上传过在信息导致请求迟迟完不成)
- POST请求基于请求主体传参,相对来说不好被劫持,比较安全
HTTP1.0 HTTP1.1 HTTP2.0
http1.0:
1.单工。因为是短连接,客户端发起请求之后,服务端处理完请求并收到客户端的响应后即断开连接。
2.HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。
3.HTTP/1.0时期,使用的是Expires
http1.1:
1.半双工。默认开启长连接keep-alive,开启一个连接可发送多个请求。
2.HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
3.HTTP/1.1使用的是Cache-Control。
http2.0:
1.全双工,允许服务端主动向客户端发送数据。
2.服务端推送, http2.0引入了server push,在浏览器明确地请求之前,它允许服务端推送资源给浏览器,免得客户端再次创建连接发送请求到服务器端获取。这样客户端可以直接从本地加载这些资源,不用再通过网络。
3.头部数据压缩, 在HTTP1.1中,HTTP请求和响应都是由状态行、请求/响应头部、消息主体三部分组成。一般而言,消息主体都会经过gzip压缩,或者本身传输的就是压缩过后的二进制文件,但状态行和头部却没有经过任何压缩,直接以纯文本传输。HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。
HTTP的状态码
响应分为五类:信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误 (500–599)
常见的状态码:
1xx(临时响应)
100: 请求者应当继续提出请求。
101(切换协议) 请求者已要求服务器切换协议,服务器已确认并准备进行切换。
2xx (3种)
200 OK:表示从客户端发送给服务器的请求被正常处理并返回;
201:表示资源被正确的创建。比如说,我们 POST 用户名、密码正确创建了一个用户就可以返回 201。
202:请求是正确的,但是结果正在处理中,这时候客户端可以通过轮询等机制继续请求。
204 No Content(不返回资源):表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
3xx (5种)
301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;
302与303的区别:后者明确表示客户端应当采用GET方式获取资源
304 Not Modified(服务器未满足附带条件)(文件未修改,可以直接使用缓存的文件):表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求未满足条件的情况下返回状态码;
307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
4xx (4种)
400 Bad Request:表示请求报文中存在语法错误;
401 Unauthorized:请求未经授权,无法访问。(比如说没有带上token)
403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
404 Not Found:表示服务器上无法找到请求的资源,比如输入了错误的URL。除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
5xx (2种)
500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
https
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
通信流程
1、客户端发起 HTTPS 请求
这个没什么好说的,就是用户在浏览器里输入一个 https 网址,然后连接到 server 的 443 端口。
2、服务端的配置
采用 HTTPS 协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请,区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面(startssl 就是个不错的选择,有 1 年的免费服务)。
这套证书其实就是一对公钥和私钥,如果对公钥和私钥不太理解,可以想象成一把钥匙和一个锁头,只是全世界只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。
3、传送证书
这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等。
4、客户端解析证书
这部分工作是有客户端的TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警告框,提示证书存在问题。
如果证书没有问题,那么就生成一个随机值,然后用证书对该随机值进行加密,就好像上面说的,把随机值用锁头锁起来,这样除非有钥匙,不然看不到被锁住的内容。
5、传送加密信息
这部分传送的是用证书加密后的随机值,目的就是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。
6、服务端解密信息
服务端用私钥解密后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加密,所谓对称加密就是,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,所以只要加密算法够彪悍,私钥够复杂,数据就够安全。
7、传输加密后的信息
这部分信息是服务段用私钥加密后的信息,可以在客户端被还原。
8、客户端解密信息
客户端用之前生成的私钥解密服务段传过来的信息,于是获取了解密后的内容,整个过程第三方即使监听到了数据,也束手无策。
http与https的区别
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
三次握手和四次挥手
原理:所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。 (2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。 (3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。 (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状态,完成四次挥手。
两次握手为什么不行
即两次握手会造成消息滞留情况下,服务器重复接受无用的连接请求
SYN 报文,而造成重复分配资源。
为什么建立连接是三次握手,而关闭连接却是四次挥手
这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。
总结:服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发送,从而比三次握手导致多了一次。
从输入url到页面加载完成发生了什么?
1、浏览器的地址栏输入URL并按下回车。 2、浏览器查找当前URL是否存在缓存,并比较缓存是否过期。 3、DNS解析URL对应的IP。 4、根据IP建立TCP连接(三次握手)。 (Chrome 在同一个域名下要求同时最多只能有 6 个 TCP 连接,超过 6 个的话剩下的请求就得等待。) 5、HTTP发起请求。
6、服务器处理请求,浏览器接收HTTP响应。得到html代码
7.浏览器解析html代码,并请求html代码中的资源
8、渲染页面,构建DOM树。
浏览器按顺序解析html文件,构建DOM树,在解析到外部的css和js文件时,向服务器发起请求下载资源,若是下载css文件,则解析器会在下载的同时继续解析后面的html来构建DOM树;若在下载js文件,解析器会停止对html的解析,这就出现了js阻塞问题。
预加载器
当浏览器被脚本文件阻塞时,预加载器(一个轻量级的解析器)会继续解析后面的html,寻找需要下载的资源。如果发现有需要下载的资源,预加载器在开始接收这些资源。预加载器只能检索HTML标签中的URL,无法检测到使用脚本添加的URL,这些资源要等脚本代码执行时才会获取。
9、关闭TCP连接(四次挥手)。
以访问百度www.baidu.com为例
首先 Chrome 搜索自身的 DNS 缓存。(如果 DNS 缓存中找到百度的 IP 地址,就跳过了接下来查找 IP 地址步骤,直接访问该 IP 地址。) 搜索操作系统自身的 DNS 缓存。(浏览器没有找到缓存或者缓存已经失效) 读取硬盘中的 host 文件,里面记录着域名到 IP 地址的映射关系,Mac 电脑中位于 /etc/hosts。(如果前1.2步骤都没有找到) 浏览器向宽带运营商服务器或者域名服务器发起一个 DNS 解析请求,这里服务器有两种方式解析请求,这在稍后会讲到,之后浏览器获得了百度首页的 IP 地址。 拿到 IP 地址后,浏览器就向该 IP 所在的服务器建立 TCP 连接(即三次握手)。 连接建立起来之后,浏览器就可以向服务器发起 HTTP 请求了。(这里比如访问百度首页,就向服务器发起 HTTP 中的 GET 请求) 服务器接受到这个请求后,根据路径参数,经过后台一些处理之后,把处理后的结果返回给浏览器,如果是百度首页,就可以把完整的 HTML 页面代码返回给浏览器。 浏览器拿到了百度首页的完整 HTML 页面代码,内核和 JS 引擎就会解析和渲染这个页面,里面的 JS,CSS,图片等静态资源也通过一个个 HTTP 请求进行加载。 浏览器根据拿到的资源对页面进行渲染,最终把完整的页面呈现给用户。 如果浏览器没有后续的请求,那么就会跟服务器端发起 TCP 断开(即四次挥手)。
创建ajax过程
1.创建一个xmlhttprequest对象 2.向服务器发送请求 利用open初始化一个请求 利用send发送请求 3.处理服务器响应,使用方法readyStatechange监测状态变化,如果状态变化,调用回调函数,如果readyState是4并且200<响应码<300,或者等于304,那么就执行成功的回调,否则就执行失败的回调。
var xmlHttp
if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest()
} else{
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP')
}
if(option.type.toLowerCase() === 'get') {
// 2. 调用open指定发送的类型和地址
xmlhttp.open('GET', url);
//3.发送请求
xmlhttp.send();
} else if (option.type.toLowerCase() === 'post') {
xmlhttp.open('POST', url);
// 4. 如果是post的话还需要设置http请求头的内容,位于open和send之间
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(str);
}
// 5. 处理服务器的响应,使用readyStatechange监测状态的变化,触发回调函数
// 6. 如果readyState是4,并且响应码处于200,300,或是等于304,就执行成功的回调
xmlHttp.onreadyStateChange = function () {
// 返回一个 XMLHttpRequest
if (xmlHttp.readyState == 4) {
// 服务器返回的状态码
if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status === 304) {
console.log(xmlhttp.responseText)
}
} else {
console.log(xmlhttp.status)
}
}
浏览器本地存储cookies sessionStorage和localstorage区别
相同点:都存储在客户端 不同点:1.存储大小
· cookie数据大小不能超过4k。
· sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
2.有效时间
· localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;不能跨域存储
· sessionStorage 数据在当前浏览器窗口关闭后自动删除。
· cookie 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
- 数据与服务器之间的交互方式
· cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端
· sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
浏览器缓存
浏览器缓存就是HTTP缓存机制,HTTP缓存有多种规则,根据是否需要向服务器重新发起请求来分类,将其分为强制缓存,协商缓存。
强制缓存:判断HTTP首部字段:Expires 和 cache-control。
Expires是一个绝对时间,即服务器时间。浏览器检查当前时间,如果还没到失效时间就直接使用缓存文件。但是该方法存在一个问题:服务器时间与客户端时间可能不一致
cache-control中的max-age保存了一个相对时间。例如Cache-Control: max-age = 484200,表示浏览器收到文件后,缓存在484200s内有效。 如果同时存在cache-control和Expires,浏览器总是优先使用cache-control。
协商缓存:通过HTTP的 last-modified(最新-改进),Etag字段进行判断。
last-modified(服务器返回的响应头中) 表示请求的URL(资源)最后一次更新的时间。下一次浏览器请求资源时就会带上if-modified-since(浏览器的请求头中)字段。服务器收到请求后,用本地Last-modified时间与if-modified-since时间比较,如果不一致则认为缓存已过期并返回新资源给浏览器;如果时间一致则发送304状态码,让浏览器继续使用缓存。
Etag:资源的实体标识(哈希字符串),当资源内容更新时,Etag会改变。服务器会判断Etag是否发生变化,如果变化则返回新资源,否则返回304。
优先级 强制缓存>协商缓存
浏览器缓存位置
浏览器中的缓存位置一共有四种,按优先级从高到低排列分别是:
- Service Worker
- Memory Cache
- Disk Cache
- Push Cache
储存策略
- 比较大的JS、CSS文件会直接被丢进磁盘,反之丢进内存
- 内存使用率比较高的时候,文件优先进入磁盘
http缓存首部字段
Expires:响应头,代表该资源的过期时间
Cache-Control:请求/响应头,缓存控制字段,精确控制缓存策略
If-Modified-Since:请求头,资源最近修改时间,由浏览器告诉服务器
Last-Modified:响应头,资源最近修改时间,由服务器告诉浏览器
Etag:响应头,资源标识,由服务器告诉浏览器
If-None-Match:请求头,缓存资源标识,由浏览器告诉服务器
DNS域名解析
DNS域名解析(域名解析),DNS实际上是一个域名和IP对应的数据库。
IP地址往都难以记住,但机器间互相只认IP地址,于是人们发明了域名,让域名与IP地址之间一一对应,它们之间的转换工作称为域名解析,域名解析需要由专门的域名解析服务器来完成,整个过程是自动进行的。
首先浏览器先检查本地hosts文件是否有这个网址映射关系,如果有就调用这个IP地址映射,完成域名解析。 如果没找到则会查找本地DNS解析器缓存,如果找到则返回。 如果还是没有找到则会查找本地DNS服务器,如果找到则返回。
最后迭代查询,按根域服务器库(.com,.cn,.vip,.top...)->顶级域(.com),然后根据顶级域(.com)->第二层域子域(baidu.com),最后根据baidu.com的域名找到相应的IP,返回给浏览器。
CSS
css3
flex布局
grid布局
@keyframes 动画
transition
transform ---- translate scale rotate
border-radius
画一个三角形
<style>
div{
width: 0px;
height: 0px;
border: 100px solid red;
border-color: red transparent transparent transparent;
}
</style>
<body>
<div></div>
</body>
不设置宽度或高度
块级元素
默认宽度由父级决定 100%
默认高度由子元素撑起
flex布局中:
flex子元素不设置高度,会被flex父元素拉伸
Position
1.绝对定位
position:absolute 脱标
相对于 static 定位以外的第一个父元素进行定位。
2.相对定位
positon:relative 不脱标
相对元素原来的位置进行定位
3.固定定位 position:fixed 脱标
相对于浏览器窗口进行定位。
标准文档流
文档流指的是元素排版布局过程中,元素会自动从左往右,从上往下的流式排列。并最终窗体自上而下分成一行行,并在每行中从左至右的顺序排放元素。
媒体查询
- 使用@media查询,可以针对不同的媒体类型定义不同的样式
- @media可以针对不同的屏幕尺寸设置不同的样式
- 当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面
- 目前针对很多苹果手机、Android手机,平板等设备都用得到媒体查询
实现宽高固定比
##
<style>
*{
padding: 0px;
margin: 0px;
}
#out{
width: 400px;
background: red;
}
#inner{
width: 100%;
height: 0px;
padding-bottom: 75%;
}
</style>
<body>
<div id="out">
<div id="inner"></div>
</div>
</body>
主要根据padding-bottom、padding-top属性设置百分比会根据父元素的宽度来决定大小,从而撑起元素。
产生层叠上下文
-
HTML中的根元素<html></html>本身j就具有层叠上下文,称为“根层叠上下文”。 -
普通元素设置
position属性为非static值并设置z-index属性为具体数值,产生层叠上下文。 -
CSS3中的新属性也可以产生层叠上下文。
父元素的display属性值为flex|inline-flex,子元素z-index属性值不为auto的时候,子元素为层叠上下文元素; 元素的opacity属性值不是1; 元素的transform属性值不是none; 元素mix-blend-mode属性值不是normal; 元素的filter属性值不是none; 元素的isolation属性值是isolate; will-change指定的属性值为上面任意一个; 元素的-webkit-overflow-scrolling属性值设置为touch。
层叠上下文的规则比较
1.同一个层叠上下文中相比较
2.
使元素居中显示
1.text-align:center方式(不脱标)
在块级父容器中让行内元素或者类行内元素居中(内部元素是块级元素则失效)只需使用 text-align: center, 这种方法可以让 inline/inline-block/inline-table/inline/flex 居中。
2.margin:0 auto方式(不脱标)
这种对齐方式要求内部元素(.content_text)是块级元素,并且不能脱离文档流(如设置position:absolute),否则无效。
3.利用position的方式(脱标)
position:absolute
top:50%
left:50%
margin-top: -元素高的一半
margin-left: -元素宽的一半
4.display:table-cell(脱标)
display:table-cell配合width,text-align:center,vertical-align:middle让大小不固定元素垂直居中,这个方式将要对其的元素设置成为一个td,float、absolute等属性都会影响它的实现,不响应margin属性;
5.垂直居中(脱标)
行内元素的垂直居中把height和line-height的值设置成一样的即可。
6.使用css3的translate水平垂直居中元素(脱标)
这种方式将脱离文档流的元素,设置top:50%,left:50%,然后使用transform来向左向上偏移半个内元素的宽和高。
7.flex布局
父元素定义
display: flex
justfity-content:center
align-items:center
使子元素垂直居中
css中的长度单位
px表示像素 (计算机屏幕上的一个点:1px = 1/96in),是绝对单位,不会因为其他元素的尺寸变化而变化;
em表示相对于父元素的字体大小。em是相对单位 ,没有一个固定的度量值,而是由其他元素尺寸来决定的相对值。
rem表示相对长度单位。其中r是root的缩写,是相对根元素的字体大小。
vw和vh:相对长度单位。是相对视口的宽度和高度,而不是父元素的。CSS中的百分比是相对其最近的父元素的宽度和高度。1vh=1/100的视口高度 1vw=1/100的视口宽度 例如:浏览器宽度是 1200px,高度是 900px。那么1vw = 1200px/100 = 12px,1vh = 900px/100 = 9px.
浮动的作用,后果,如何清除浮动
说明:
1.浮动会让元素脱离标准文档流,俗称脱标
2.浮动可以让元素浮到第二层,而其他没有浮动的元素就往上排
作用:
1.行内元素在浮动之后,可以进行宽高的定义
2.文本会给浮动的元素让位,可以制作成文本环绕的效果。
后果:
1.在父级没有高度的情况下,让子级浮动,结果会导致撑不起父级。(让父级没有高度,如果不浮动的话,可以把父级撑起来)
清除浮动:
1.在父级内容的最后添加一个空的div,并且添加clear属性。(并不推荐使用,因为会添加大量的无用标签,让页面变得复杂)
例如 :
clear:left -------清除左侧浮动
clear:right -------清除右侧浮动
clear:both -------清除所有浮动
2.给父级设置overflow:hidden;属性(溢出隐藏),会触发bfc(块级格式化上下文),并不推荐使用,在和定位一起使用的时候,会产生其他问题。
3.使用伪元素 :after (推荐使用)
.clear:after{
content: ""; /内容为空/
height: 0;
line-height: 0;
display: block; /块级元素/
visibility: hidden; /隐藏/
clear: both; /清除浮动/
}
BFC(块级格式化上下文)
说明:具有BFC属性的元素也属于普通流定位方式,与普通容器没有什么区别,但是在功能上,具有BFC的元素可以看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且具有普通容器没有的一些特性,比如包含浮动元素,以防止出现高度塌陷问题。总之,BFC就是一种属性,这种属性会影响着元素的定位及与其兄弟元素之间的相互作用。
特点:
BFC会阻止外边距折叠
折叠:两个相邻的盒子(可能是兄弟关系也可能是祖先关系)的垂直外边距可以合并成一个单独的垂直外边距。这种合并外边距的方式被称为折叠。
在同一个BFC中,两个相邻的块级元素在垂直方向上的外边距会发生叠加,具体的叠加规则如下:
- 当两个块级元素的外边距都为正数时,取较大者
- 当两个块级元素的外边距都为负数时,取较大者
- 当一正一负时,为两者的和
BFC可以包含浮动元素
子元素使用float,会让父元素高度塌陷,如果触发BFC,父元素高度不会塌陷
BFC可以阻止元素被浮动元素覆盖
如何触发BFC:
- 浮动元素:float除none以外的值
- 绝对定位元素:position(absolute、fixed)
- display为以下其中之一的值inline-block、flex、inline-flex、table-cell、table-caption
- overflow除了visible以外的值(hidden、auto、scroll)
link 和@import 的区别是?
(1)、link属于HTML标签,而@import是CSS提供的; (2)、页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载; (3)、import只在IE5以上才能识别,而link是HTML标签,无兼容问题; (4)、link方式的样式的权重 高于@import的权重.
样式优先级的规则
选择器的优先级
1.在属性后面使用!important会覆盖页面内任何位置定义的元素样式。
2.作为style属性写在元素内的样式。
3.id选择器 #item{}
4.类选择器 .item{}
5.标签选择器 item{}
6.通配符选择器 *{}
引入方式决定优先级
行内样式的优先级要高于嵌入和外链,嵌入和外链如果使用的选择器相同就看他们在页面中插入的顺序,在后面插入的会覆盖前面的。
继承样式
优先级较低
浏览器默认样式
优先级最低
盒子模型
盒子模型由 html元素的内容content+内边距padding+边框border+外边距margin组成
box-sizing常用的属性有哪些?分别有什么作用?
属性值
· box-sizing:content-box //默认形式
· box-sizing:border-box //宽度包括了padding,border 不包括margin
· box-sizing:inherit
隐藏一个元素的方法
- display: none:渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。
- visibility: hidden:元素在页面中仍占据空间,但是不会响应绑定的监听事件。
- opacity: 0:将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
- position: absolute:通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。
- z-index: 负值:来使其他元素遮盖住该元素,以此来实现隐藏。
- clip/clip-path :使用元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
- transform: scale(0,0) :将元素缩放为 0,来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
伪类选择器
用于选取未被访问的链接。
a:link {
color: #FF0000;
}
/* 已访问的链接 */
a:visited {
color: #00FF00;
}
/* 鼠标悬停链接 */
a:hover {
color: #FF00FF;
}
/* 已选择的链接 */
a:active {
color: #0000FF;
}
在下面的例子中,选择器匹配作为任何元素的第一个子元素的任何 <p> 元素:
p:first-child {
color: blue;
}
在下面的例子中,选择器匹配所有 <p> 元素中的第一个 <i> 元素:
p i:first-child {
color: blue;
}
选择作为其父的第二个子元素的每个 <p> 元素。
p:nth-child(2)
选择作为父的第二个子元素的每个<p>元素,从最后一个子元素计数。
p:nth-last-child(2)
伪元素选择器
伪类和伪元素的区别
1.伪类本质上是为了弥补常规CSS选择器的不足,以便获取到更多信息; 2.伪元素本质上是创建了一个有内容的虚拟容器; 3.CSS3中伪类和伪元素的语法不同;伪类用单冒号:表示;而伪元素用双冒号::表示。 4.可以同时使用多个伪类,而只能同时使用一个伪元素;
HTML
html语义化
HTML语义化:就是页面去掉样式或者加载失败的时候能够让页面呈现出清晰的结构。HTML5新增了好多语义化的标签,例如:header、footer、nav、menu、section、article等等,单单从字面上理解,就知道标签的含义。在写页面的时候,我们可以直接引用这些标签,不需要再用没有任何含义的div标签了,对于机器可以识别,对于开发人员很容易明白。这就是HTML语义化。
语义化的好处:
1)为了在没有CSS的情况下,页面也能呈现出很好地内容结构、代码结构 2)用户体验:例如title、alt用于解释名词 3)有利于SEO:利于被搜索引擎收录,更便于搜索引擎的爬虫程序来识别 4)方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页 5)便于项目的开发及维护,使HTML代码更具有可读性
Doctype
声明位于文档中的最前面的位置,处于标签之前。此标签可告知浏览器文档使用哪种 HTML 或 XHTML 规范。(重点:告诉浏览器按照何种规范解析页面)
H5新特性
新的语义标签和属性
标签
header标签包含引导和导航等,通常包含h1h6、搜索框、logo等。 footer标签一般配合address标签(显示地址),包含作者信息、相关链接等。 nav标签一般包含多个a标签,构建导航组件。 aside标签主要装载广告、侧边栏。 article标签包含文章,一般内嵌header、footer、h1、p标签。 section标签可以用在以上任一一个标签中划分组件。 hgroup顾名思义是h1h6的集合。
属性
document.activeElement 获得当前拥有焦点的DOM元素
document.readyState 当前文档状态 loading表示正在加载 complete表示文档加载完成
dataset 自定义数据属性 命名规范为 data-属性名
例如:
可以使用 getElementById获取DOM元素后,使用obj.dataset.appId来访问该属性(去掉前缀data-)
本地存储
h5提供了sessionStorage、localStorage和indexedDB加强本地存储。
表单新特性
以往input中的name和value要随着form表单一起提交,form表单必须包裹input , 而现在可以通过input的form属性綁定。
input-------增加了placeholder屬性,autofocus属性,页面只能有一个
视频和音频 Canvas绘图、SVG绘图 地理定位
Geolocation API访问地理位置,通过window.navigator.geolocation来实现访问。
这个对象有三个方法:
getCurrentPosition()
watchPosition()
clearWatch
拖放API
JavaScript
Object和Map的区别
Object:“有特别的顺序“,整数属性会被进行排序,其他属性则按照创建的顺序显示。
Map:迭代的顺序与插入值的顺序相同。与普通的Object不同,Map保留了此顺序。
闭包
当一个嵌套的内部函数引用了外部函数的变量时,就产生了闭包。闭包是被嵌套的内部函数。
作用:
1.闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量
2.闭包的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收。
原型
ES6新特性
let const 箭头函数 promise 模版字符串 解构 set map
let const var 区别
区别1:
使用 let / const 声明的全局变量,会被绑定到Script对象而不是Window对象,不能以Window.xx 的形式使用;
使用 var 声明的全局变量会被绑定到Window对象;
使用var / let / const 声明的局部变量都会被绑定到 Local 对象。
注:Script对象、Window对象、Local对象三者是平行并列关系。
区别2:
var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。 (函数作用域)
区别3:
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。 (块级作用域)
区别4:
const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。(块级作用域)
区别5:
let和const不能重复声明,var可以。
ECMAScript数据类型
ECMAScript6+ 有 8 种数据类型,即
基本数据类型:Undefined、Null、Boolean、Number 、String、Symbol
引用数据类型:Object(function、array)
es6新增基本数据类型:bigint。
声明提升
var可以变量提升,let,const不能变量提升(其实let和const的创建也被提升了,但是初始化未被提升 // 这就是let const的暂时性死区)
JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。函数提升会优先于变量提升
JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。
JavaScript 初始化(给变量赋值)不会提升
箭头函数和普通函数的区别
1.箭头函数没有this。(所以他并不能使用bind,call,apply改变this指向)
2.箭头函数没有prototype。
3.箭头函数没有arguments。
4.箭头函数的语法简单。
宏任务和微任务(属于异步任务)
宏任务
(macro)task,可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。
浏览器为了能够使得JS内部(macro)task与DOM任务能够有序的执行,会在一个(macro)task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染,流程如下:
(macro)task->microtask->渲染->(macro)task->...
微任务
microtask,可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。
所以它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染。也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前)。
微任务包括: promise 的回调、node 中的 process.nextTick 、对 Dom 变化监听的 MutationObserver
宏任务包括: script 脚本的执行、setTimeout ,setInterval ,setImmediate 一类的定时事件,还有如 I/O 操作、UI 渲染等
event loop(事件循环)
Event Loop 执行顺序:
-
首先执行同步代码,
-
当执行完所有同步代码后,执行栈为空,查询是否有异步代码需要执行 ,如果有放到相应任务队列中
- 先执行微任务
- 当执行完所有微任务后,如有必要会渲染页面
- 再执行宏任务
-
然后开始下一轮 Event Loop
JS数据类型有哪些?
JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。
检测数据类型
-
typeof:返回检测的数据类型,数组、对象、null都会被判断为object
-
instanceof:返回true/false,只能正确判断引用数据类型,运行机制是判断在其原型链中能都找到该类型的原型
-
constructor:返回true/false,可判断所有数据类型
-
Object.prototype.toString.call() :返回检测的数据类型,可判断所有数据类型
typeof 可以准确地判断出除了null之外的基本数据类型 instanceof 可以判断出复杂数据类型,但是判断不出基本数据类型。
js数组操作---改变原数组和不改变原数组的方法整理
一、改变原始数组的方法:
1、pop()
删除 arrayObject 的最后一个元素,把数组长度减 1,并且返回它删除的元素的值。如果数组已经为空,则 pop() 不 改变数组,并返回 undefined 值。arrayObject.pop() 。
2、push()
push() 方法可把它的参数顺序添加到 arrayObject 的尾部。它直接修改 arrayObject,而不是创建一个新的数组,arrayObject.push(newelement1,newelement2,….,newelementX) 。
3、reverse()
该方法会改变原来的数组----将原来的数组倒序,而不会创建新的数组。arrayObject.reverse()。
4、shift()
删除数组的第一个元素,并返回第一个元素的值,如果数组是空的,那么 shift() 方法将不进行任何操作。
5、unshift()
unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。arrayObject.unshift(newelement1,newelement2,….,newelementX)返回arrayObject 的新长度。
6、sort()
对数组的引用。请注意,数组在原数组上进行排序,不生成副本。arrayObject.sort(sortby) (如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。 如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。 若 a 等于 b,则返回 0。 若 a 大于 b,则返回一个大于 0 的值。)
7、splice()
splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。 如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组 arrayObject.splice(index,howmany,item1,…..,itemX) 。
二、不改变原始数组的方法:
1、concat()
用于连接两个或多个数组,仅会返回被连接数组的一个副本,arrayObject.concat(arrayX,arrayX,……,arrayX) 。
2、join()
返回一个字符串。该字符串是通过把 arrayObject 的每个元素转换为字符串,然后把这些字符串连接起来,arrayObject.join(separator) 。
3、slice() ----py中的切片
arrayObject.slice(start,end)返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。
4、JSON.parse(JSON.stringify(array))
这种方式会重新复制一个数组。也是实现深拷贝的一种方式。
判断数组是否相等
使用toString()方法
arr1.toString() === arr2.toString()
数组去重
方法一:
双层循环,外层循环元素,内层循环时比较值
如果有相同的值则跳过,不相同则push进数组
方法二:利用splice直接在原数组进行操作
双层循环,外层循环元素,内层循环时比较值
值相同时,则删去这个值
方法三:利用ES6的set
Array.from(new Set(array))
字符串slice() substr() substring()
都是提取子字符串的方法。第一个参数都表示开始的位置
slice() 、substring()第二个参数表示结束的位置
substr()第二个参数表示提取的子字符串的字符数
当传入参数为负数时,
slice()将所有为负的参数变为为字符串长度加上这个负数值
substring()会将所有为负数的参数变为0
substr()第一个参数为负,变为字符串长度加上这个负数值。第二个参数为负,变为0
判断是否包含某个其他字符串的方法 startsWith() endsWith() includes()
startsWith()判断是否以某个字符串开始,第二个参数可以指定搜索开始的位置
endsWith() 判断是否以某个字符串结束,第二个参数指定判断的字符串的长度 例如:‘bazbaz’.endsWith('baz',3) =====> ‘baz’.endsWith('baz')
includes() 判断是否包含某个字符串,第二个参数可以指定搜索开始的位置
JS继承的实现方式
1、原型链继承
2、构造继承
3、实例继承
浅拷贝和深拷贝
浅拷贝:
1.Object.assign方法
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign({},obj);
obj1.a = 3;
console.log(obj.a) // 3
2.直接用=赋值
let a=[0,1,2,3,4],
b=a;
console.log(a===b);
a[0]=1;
console.log(a,b);
深拷贝
1.通过JSON对象来实现深拷贝
function deepClone(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
}
缺点: 无法实现对对象中方法的深拷贝,会显示为undefined,可以实现数组或对象深拷贝,但不能处理函数和正则
2.通过jQuery的extend方法实现深拷贝
var oldarray = [1,2,3,4];
var newArray = $.extend(true,[],oldarray); // true为深拷贝,false为浅拷贝
3.手动实现深拷贝
let obj1 = {
a: 1,
b: 2
}
let obj2 = {
a: obj1.a,
b: obj1.b
}
obj2.a = 3;
alert(obj1.a); // 1
alert(obj2.a); // 3
防抖和节流
防抖和节流本质是不一样的。防抖是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。
JS事件冒泡和事件代理
事件冒泡:当一个元素接收到事件的时候,会把他接收到的事件传给父级,一直传到window
注意这里传递的仅仅是事件 并不传递所绑定的事件函数。所以如果父级没有绑定事件函数,就算传递了事件 也不会有什么表现 但事件确实传递了。
阻止冒泡的方法
1.事件委托: 将元素的绑定事件写起其父元素上,防止事件冒泡
2.event.stopPropagation(): 可以阻止事件冒泡,阻止父级元素的绑定事件
son.addEventListener('click',function(e){ alert('son') e.stopPropagation(); //阻止事件冒泡 })
事件流
事件流:当事件发生时,会在发生事件的元素节点与DOM树根节点之间按照特定的顺序进行传播, 这个过程称之为事件流。
事件流可分为冒泡型事件流、捕获型事件流。
事件冒泡和事件捕获
VUE
MVVM和MVC
MVVM包括view视图层、model数据层、viewmodel层。各部分通信都是双向的。采用双向数据绑定,View的变动,自动反映在 ViewModel,反之亦然。其中ViewModel层,就是View和Model层的粘合剂,他是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他各种各样的代码的极好的地方。说白了,就是把原来ViewController层的业务逻辑和页面逻辑等剥离出来放到ViewModel层。
MVC是包括view视图层、controller控制层、model数据层。各部分之间的通信都是单向的。
View 传送指令到 ControllerController 完成业务逻辑后,要求 Model 改变状态Model 将新的数据发送到 View,用户得到反馈
Vue的生命周期
Vue实例从创建到销毁的过程就是生命周期,也就是 开始创建 -> 初始化数据 -> 编译模板 -> 挂载DOM -> 数据更新重新渲染虚拟DOM -> 最后销毁的过程;
BeforeCreate:只有一些默认的生命周期函数和默认的事件,data还没进行初始化,处于undefined;
Created:此时可以访问data里的数据和方法,没el,没挂载DOM;
BeforeMount:元素el和数据对象已有,在挂载之前还是虚拟DOM节点;
Mounted:vue实例已经挂载到真实DOM,可通过DOM操作获取DOM节点;
beforeUpdate:响应式数据更新时调用,发生虚拟DOM打补丁之前,适合在更新前访问现有的DOM;
Updated:虚拟DOM重新渲染和打补丁之后调用,组成新的DOM已经更新,避免在这个钩子函数操作数据,防止死循环;
Beforedestory:vue实例销毁之前调用,可以对不用的定时器进行清除,解绑事件;
Destoryed:vue实例销毁后调用,调用后所有事件监听器会被移除,所有子实例都会被销毁。
双向绑定实现原理
vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)。
computed和watch区别
computed 计算属性 : 依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值.
watch 侦听器 : 更多的是观察的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。
一些vue的指令
v-cloak
v-once
v-if v-else-if v-else
v-show
v-if和v-show
v-show 是通过css属性display控制元素显示,元素总是存在的。
v-if:通过控制dom来控制元素的显示和隐藏,如果一开始条件为false,元素是不存在的。
vue-router
1、hash
使用URL的hash来模拟一个完整的URL,当URL发生改变时,页面不会重新加载,其显示的网络路径中会有#号,这是最安全的模式,因为他兼容所有的浏览器和服务器
2、history
美化后的hash模式,路径中会去掉#。依赖于html5的history,pushState API,所以要担心IE9及以下的版本。并且还包括back、forward、go三个方法,对应浏览器的前进、后退、跳转操作,就是浏览器左上角的前进后退等按钮进行的操作
webpack
loader和plugin的区别
loader
由于webpack本身只能打包commonjs规范的js文件,所以针对css,图片等格式的文件没法打包,就需要引入第三方的模块进行打包。
loader 扩展了webpack,只专注于转化文件这一个领域,完成压缩 / 打包 / 语言翻译等,仅仅只是为了打包,仅仅只是为了打包。
如 css-loader 和 style-loader 模块,是为了打包css的
如 babel-loader 和 babel-core 模块,是为了把es6的代码 转成 es5
如 url-loader 和 file-loader,是为了把图片进行打包
plugin
plugin也是为了扩展webpack的功能,plugin是作用于webpack本身的;
从打包优化到压缩,到重新定义环境变量,webpack提供了很多开箱即用的插件:
如 CommonChunkPlugin 主要用于提取第三方库和公共模块,避免首屏加载的bundle文件 或者 按需加载的bundle文件体积过大,导致加载时间过长,是优化的利器
注:CommonsChunkPlugin于4.0及以后被移除,使用SplitChunksPlugin替代
如 html-webpack-plugin 用于html文件的拷贝,打包,还给html中自动增加了引入打包后的js文件的代码 ,还能指明把js文件引入到html文件的底部等,
webpack构建流程
webpack的启动之后,递归解析Entry依赖中所有的Module,每找到一个Module,就会根据Module.rules里配置的Loader规则进行相应的转换处理,对Module进行转换后,在解析出当前的Module依赖的Module,这些Module会以Entry为单位进行分组,即为一个CHunk。因此一个Chunk,就是一个Entry及其所有依赖的Module合并的结果。最后Webpack会将所有Chunk转化成文件输出Output。在整个构建流程中,Webpack会在恰当的时机执行Plugin里定义的逻辑,从而完成Plugin插件的优化任务。