BFC系列问题
要使子元素顶部距离父元素100px怎么做?
解决方式:
- 为子元素加上margin-top: 100px; 然后为父元素加上overflow: hidden;形成BFC;
- 为子元素加上宽度为100px的border;
- 为父元素加上padding: 100px;
遇到那些问题需要用到BFC?
- margin重叠 (为其中一个子元素外层包裹一个div, 为此div设置position: absolute;触发BFC)
- 高度塌陷 (父元素增加overflow: hidden,触发BFC)
- 子元素浮动,父元素高度塌陷 (让外层元素产生一个 BFC)
- 浮动元素与未浮动元素之间产生间隙(让未浮动的元素产生一个BFC)
怎么触发BFC?
- 浮动元素:float 除 none 以外的值。
- 绝对定位元素:position (absolute、fixed)。
- display 为 inline-block、table-cells、flex。
- overflow 除了 visible 以外的值 (hidden、auto、scroll)。
输入URL到渲染的过程
HTTP请求阶段
- 浏览器首先向DNS域名解析服务器发送请求
- DNS反解析:根据浏览器请求地址中的域名,到DNS服务器中找到对应的服务器外网IP地址
- 通过找到的外网IP,向对应的服务器发送请求(首先访问的是服务器的WEB站点管理工具:准确来说是我们先基于工具在服务器上创建很多服务)
- 通过URL地址中携带的端口号,找到服务器上对应的服务,以及服务所管理的项目源文件。
HTTP响应阶段
- 服务器端根据请求地址中的路径名称、问号传参或者哈希值,把客户端需要的内容进行准备和锤
- 把准备的内容响应给客户端(如果请求的是HTML或者CSS等这样的资源文件,服务器返回的是资源文件中的源代码【不是文件本身】)
浏览器渲染阶段
客户端浏览器接收到服务器返回的源代码,基于自己内部的渲染引擎(内核)开始进行页面的绘制和渲染
- 首先计算DOM结构
- 生成DOM TREE
- 自上而下运行代码
- 加载CSS等资源内容
- 根据获取的CSS生成带样式的RENDER-TREE
- 开始渲染和绘制
为什么要3次握手和4次挥手?
3次握手过程
-
客户端发送连接请求(第1次握手)
-
服务端返回收到了该请求的确认(第2次握手)
-
客户端发送收到了服务端确认的确认(第3次握手)
为什么要3次?2次握手为什么不行?
为了避免Client
本该失效的请求被Server
接收, 必须要多一次握手, 即三次握手。
其实2次握手可以完成连接的建立,但会带来资源浪费的问题
假设通信道路堵塞,第1次的请求未能在限定时间内收到服务端的请求,可能堵塞也可能丢失,于是发送第2次请求
堵塞结束后,2次的请求自然建立了2个TCP连接,但问题是,第1个连接已经被客户端放弃了(因为之前的超时客户端不会在
这个连接上传输数据),而服务端开启了2个连接。此时只有第2个连接是有用的,第1个连接自然就造成了资源的浪费。
4次挥手
结束和建立的一个区别在于, Client
想建立的时候, Server
能够随时准备建立.而Client
想结束的时候, Server
得先确保手中的数据发送完才能够结束。
为什么需要4次挥手?
因为TCP的连接只能由客户端开始放弃,服务端只能被动接受,客户端放弃连接后
服务端的数据可能没传输完,所以需要4次挥手才能确保全双工通信的关闭。
script标签会阻塞加载吗?有什么解决办法
会引起阻塞
解决办法
CSS会阻塞加载吗?
- css加载不会阻塞DOM树的解析
- css加载会阻塞DOM树的渲染
- css加载会阻塞后面js语句的执行
因此,为了避免让用户看到长时间的白屏时间,我们应该尽可能的提高css加载速度,比如可以使用以下几种方法:
- 使用CDN(因为CDN会根据你的网络状况,替你挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)
- 对css进行压缩(可以用很多打包工具,比如webpack,gulp等,也可以通过开启gzip压缩)
- 合理的使用缓存(设置cache-control,expires,以及E-tag都是不错的,不过要注意一个问题,就是文件更新后,你要避免缓存而带来的影响。其中一个解决防范是在文件名字后面加一个版本号)
- 减少http请求数,将多个css文件合并,或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)
浏览器缓存相关问题
网页第二次加载的时候比较快,为什么?
第一次加载时,所有资源都需要从服务器加载一遍。
第二次加载时,因为浏览器有缓存,css,js等资源都直接从缓存中获取。
强缓存和协商缓存
强缓存
主要看http header中的expires字段,会指定资源过期时间,在该时间之前,则不会去请求服务端数据。并且依赖于客户端,即客户端可以通过修改本地的时间跳过校验。
协商缓存
请求资源时,把用户本地该资源的 etag 同时带到服务端,服务端和最新资源做对比。
- 如果资源没更改,返回304,浏览器读取本地缓存。
- 如果资源有更改,返回200,返回最新的资源。
http/1.1 会更将last-modified的时间发送给服务端判断,当前的资源是否修改。last-modified:文件的修改时间,精确到秒
http/1.1 另一种协商缓存是使用Etag,将Etag发送给服务端,判断当前的资源是否修改。etag:每个文件有一个,改动文件了就变了,就是个文件hash,每个文件唯一
304协商缓存
浏览器缓存分为强制缓存和协商缓存,优先读取强制缓存。
强制缓存分为expires和cache-control,而expires是一个特定的时间,是比较旧的标准和cache-control通常是一个具体的时间长度,比较新,优先级也比较高。
而协商缓存包括etag和last-modified,last-modified的设置标准是资源的上次修改时间,而etag是为了应对资源修改时间可能很频繁的情况出现的,是基于资源的内容计算出来的值,因此优先级也较高。
协商缓存与强制缓存的区别在于强制缓存不需要访问服务器,返回结果是200,协商缓存需要访问服务器,如果命中缓存的话,返回结果是304。
301永久移动
请求的资源已被永久移动到新URL,返回信息会包括新的URL,浏览器会自动定向到新URL,今后任何新的请求都应该使用新的URL代替
302 临时移动
与301类似,但是资源只是临时被移动,客户端应该继续使用原有的URL
虚拟DOM的原理
简单概括有3点:
-
用JavaScript模拟DOM树,并渲染这个DOM树
-
比较新老DOM树,得到比较的差异对象
-
把差异对象应用到渲染的DOM树
Diff的差异有4中情况:
- 直接替换原有节点
- 调整子节点,包括移动、删除等
- 修改节点属性
- 修改节点文本内容
readyState(AJAX状态码)
状态码 | 状态 | 状态描述 |
0 | unsent | 未发送,只是创建了xhr,还没有发送; |
1 | opened | 请求打开,已经执行完xhr.open这个操作; |
2 | headrs_recevied | 前ajax请求已经发送,响应头信息已经被客户端接收,服务器端响应已经返回的http状态码; |
3 | loading | 响应主体内容正在返回的路上; |
4 | done | 响应主体内容已经返回到客户端 |
async/await
await的执行规则:
function A(){
console.log(2);
return 10;
}
async function B(){
console.log(1);
let result = await A();
console.log(result);
console.log(3);
}
B();
console.log(4);
//输出结果:1 2 4 10 3
- 先把await后面的方法执行,返回一个promise的实例;
- 它会跳出当前正在执行的函数,也就是await下面的代码行暂时先不执行(把下面的代码行从主栈中移除,放到等待队列中);
- 当主栈中的其他任务完成,即主栈空闲,并且promise也已经计算出最后的结果,再把之前第二步移到等待队列中的代码,重新放到主栈中执行。
Generator
Generator函数是ES6提供的一种异步编程解决方案。通过yield标识位和next()方法调用,实现函数的分段执行。