1.0.1+0.2===0.3吗,为什么?
js采用IEEE 754的双精度64位浮点数标准,存在精度缺失。解决:设置一个误差范围值,通常称为”机器精度“,js中这个值通常是2^-52 ,ES6中Number.EPSILON这个值正等于2^-52 。只要判断(0.1+0.2)-0.3小于Number.EPSILON,在这个误差的范围内就可以判定0.1+0.2===0.3为true
2.Number()的存储空间是多大,如果后台发送了一个超过最大字节的数字怎们办?
js的number类型有个最大值(安全值)。即2的53次方,为9007199254740992。如果超过这个值,那么js会出现不精确的问题。这个值为16位。
解决大数运算:
- 将大数的每一位存进数组,然后对两个数组的每一个位单独运算,得到运算结果。
- 使用插件
- 字符串转换
3.垂直居中实现方式
-
通过设置div的transform: translateY(-50%),意思是使得div向上平移(translate)自身高度的一半(50%) ,不必提前知道居中元素的尺寸
html,body { width: 100%; height: 100%; margin: 0; padding: 0; } .content { width: 300px; height: 300px; background: orange; margin: 0 auto; /*水平居中*/ position: relative; top: 50%; /*偏移*/ margin-top: -150px; / transform: translateY(-50%); } 复制代码
-
flex
body { display: flex; align-items: center; /*定义body的元素垂直居中*/ justify-content: center; /*定义body的里的元素水平居中*/ } .content { width: 300px; height: 300px; background: orange; } 复制代码
#box { width: 300px; height: 300px; background: #ddd; display: flex; flex-direction: column; justify-content: center; } #child { width: 300px; height: 100px; background: #08BC67; line-height: 100px; } 复制代码
-
绝对定位和负外边距。兼容性不错,但是有一个小缺点:必须提前知道被居中块级元素的尺寸
#box { width: 300px; height: 300px; background: #ddd; position: relative; } #child { width: 150px; height: 100px; background: orange; position: absolute; top: 50%; margin: -50px 0 0 0;// 居中高度的二分之一 line-height: 100px; } 复制代码
-
绝对定位结合margin: auto。实现方式的两个核心是:把要垂直居中的元素相对于父元素绝对定位,top和bottom设为相等的值
#box { width: 300px; height: 300px; background: #ddd; position: relative; } #child { width: 200px; height: 100px; background: #A1CCFE; position: absolute; top: 0; bottom: 0; margin: auto; line-height: 100px; } 复制代码
-
使用 line-height 对单行文本进行垂直居中
#box{ width: 300px; height: 300px; background: #ddd; line-height: 300px; } #box img { vertical-align: middle; } 复制代码
-
使用 display 和 vertical-align 对容器里的文字进行垂直居中
#box { width: 300px; height: 300px; background: #ddd; display: table; } #child { display: table-cell; vertical-align: middle; } 复制代码
-
vertical-align属性只对拥有valign特性的html元素起作用,例如表格元素中的等等,而像
这样的元素是不行的。
valign属性规定单元格中内容的垂直排列方式,语法:,value的可能取值有四种:
top:对内容进行上对齐
middle:对内容进行居中对齐
bottom:对内容进行下对齐
baseline:基线对齐
4.什么是BFC,形成原理是什么?
-
BFC(block formatting context)块级格式化上下文 ,它是指一个独立的块级渲染区域,只有Block-level BOX参与,该区域拥有一套渲染规则来约束块级盒子的布局,且与区域外部无关。
-
在进行盒子元素布局的时候,具有BFC特性的元素可以看做是隔离了的独立容器 ,在这个环境中按照一定规则进行布局不会影响到其它环境中的布局。 比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。 也就是说,如果一个元素符合了成为BFC的条件,该元素内部元素的布局和定位就和外部元素互不影响(除非内部的盒子建立了新的 BFC),是一个隔离了的独立容器。(在 CSS3 中,BFC 叫做 Flow Root)。 通俗一点来讲,可以把BFC理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海都不会影响到外部。
-
BFC形成条件:
- body 根元素
- 浮动元素,float 除 none 以外的值
- 绝对定位元素,position(absolute,fixed)
- display 为以下其中之一的值 inline-blocks,table-cells,table-captions
- overflow 除了 visible 以外的值(hidden,auto,scroll)
-
规则是作用于BFC内部的元素,而条件则是作用于BFC容器的,这点要理解
-
BFC约束规则:
- 内部的Box会在垂直方向上一个接一个的放置
- 属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关。(margin取较大的那一边)
- 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明BFC中子元素不会超出他的包含块,而position为absolute的元素可以超出他的包含块边界)
- BFC的区域不会与float的元素区域重叠
- 计算BFC的高度时,浮动子元素也参与计算
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然
-
BFC在布局中的应用
-
阻止外边距折叠
在标准文档流中,块级标签之间竖直方向的margin会以大的为准,这就是margin的塌陷现象。可以用overflow:hidden产生bfc来解决。
如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。<head> div{ width: 100px; height: 100px; background: lightblue; margin: 100px; } </head> <body> <div></div> <div></div> </body> 复制代码
<div class="container"> <p></p> </div> <div class="container"> <p></p> </div> 复制代码
.container { overflow: hidden; } p { width: 100px; height: 100px; background: lightblue; margin: 100px; } 复制代码
-
包含浮动元素
度塌陷问题,在通常情况下父元素的高度会被子元素撑开,而在这里因为其子元素为浮动元素所以父元素发生了高度坍塌,上下边界重合,这时就可以用BFC来清除浮动了。
<div style="border: 1px solid #000;"> <div style="width: 100px;height: 100px;background: grey;float: left;"></div> </div> 复制代码
<div style="border: 1px solid #000;overflow: hidden"> <div style="width: 100px;height: 100px;background: grey;float: left;"></div> </div> 复制代码
-
阻止元素被浮动元素覆盖
div浮动兄弟这该问题:由于左侧块级元素发生了浮动,所以和右侧未发生浮动的块级元素不在同一层内,所以会发生div遮挡问题。可以给右侧元素添加 overflow: hidden,触发BFC来解决遮挡问题。 这个方法可以用来实现两列自适应布局,效果不错,这时候左边的宽度固定,右边的内容自适应宽度。
<div style="height: 100px;width: 100px;float: left;background: lightblue">我是一个左浮动的元素</div> <div style="width: 200px; height: 200px;background: grey">我是一个没有设置浮动, 也没有触发 BFC 元素, width: 200px; height:200px; background: grey;</div> 复制代码
<div style="height: 100px;width: 100px;float: left;background: lightblue">我是一个左浮动的元素</div> <div style="width: 200px; height: 200px;background: grey;overflow:hidden">我是一个没有设置浮动, 也没有触发 BFC 元素, width: 200px; height:200px; background: grey;</div> 复制代码
-
5.BFC与IFC
-
Block Formatting Context
(BFC | 块级格式化上下文) 和Inline Formatting Context
(IFC |行内格式化上下文)。 -
IFC布局规则:
在行内格式化上下文中,框(boxes)一个接一个地水平排列,起点是包含块的顶部。水平方向上的
margin
,border
和padding
在框之间得到保留。框在垂直方向上可以以不同的方式对齐:它们的顶部或底部对齐,或根据其中文字的基线对齐。包含那些框的长方形区域,会形成一行,叫做行框。 -
上一段代码
.box{ width:150px; height:150px; display:inline-block; word-wrap:break-word; background:green } 复制代码
<div class='box'>asdfasdfasdfffffffffffffffffffffffffffffffffffffffffffffffff</div> <div class='box'>asdfasdfasdf</div> 复制代码
可以看到第二个inline-block发生了下陷,这里的知识就涉及到了IFC。给第二个添加vertical-align:top;属性就可以解决问题。
-
行级盒子的宽度和高度: 高由font-size决定的,宽等于其子行级盒子的外宽度(margin+border+padding+content width)之和。 inlinebox也有自己的宽高度计算的方法,宽度取决于内部元素的宽度,最大为父元素的宽度,linebox的高度取决于linebox元素,一般由最高的元素决定linebox的高度。
-
行内元素的对齐方式,默认是baseline对齐,如上图所示。
-
inline元素的baseline位置:
- inline元素的baseline,为内容盒content-box里面文本框的基线。
- inline-block的外边缘就是margin-box的外边缘,
- 如果inline-block内部有内容,则baseline为内容最下方的baseline,参照刚才给出的例子。
- 如果Inline-block内部无内容,则baseline与margin-box的下边缘重合。
- 如果overflow属性不为visible(默认),则baseline与margin-box的下边缘重合。
6.回流与重绘,如何避免回流?
-
Dom树和Render树:
-
浏览器渲染过程:
浏览器渲染过程
-
visibility:hidden隐藏的元素还是会包含到render tree中,因为visibility:hidden会影响布局(layout),会占有空间。根据css2的标准,render tree中的每个节点都称为Box(Box demensions),理解页面元素为一个具有填充,边距,边框和位置的盒子。
-
重绘:重绘是一个元素外观的改变所触发的浏览器行为,例如改变visibility,outline,背景色属性。浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。
-
回流:回流是更明显的一种改变,可以理解为render tree需要重新计算。每个页面至少需要一次回流,就是在页面加载的时候。回流必将引起重绘,但重绘不一定引起回流。
- 添加或删除可见的DOM元素
- 元素的位置发生变化
- 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
- 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
- 页面一开始渲染的时候(这肯定避免不了)
- 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
- 激活css伪类
- 计算offsetWidth和offsetHeight等属性
-
获取布局信息的操作的时候,会强制队列刷新,比如当你访问以下属性或者使用以下方法:
- offsetTop、offsetLeft、offsetWidth、offsetHeight
- scrollTop、scrollLeft、scrollWidth、scrollHeight
- clientTop、clientLeft、clientWidth、clientHeight
- getComputedStyle()
- getBoundingClientRect
以上属性和方法都需要返回最新的布局信息,因此浏览器不得不清空队列,触发回流重绘来返回正确的值。因此,我们在修改样式的时候,**最好避免使用上面列出的属性,他们都会刷新渲染队列。**如果要使用它们,最好将值缓存起来。
-
减少重绘和回流:
-
合并多次对DOM和样式的修改,然后一次处理掉。 使用CSSText或者替换class
const el = document.getElementById('test'); el.style.padding = '5px'; el.style.borderLeft = '1px'; el.style.borderRight = '2px'; 复制代码
const el = document.getElementById('test'); el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;'; 复制代码
const el = document.getElementById('test'); el.className += ' active'; 复制代码
-
批量修改Dom,先使元素脱离文档流,再对其进行多次修改,最后将元素带回到文档中。
该过程的第一步和第三步可能会引起回流,但是经过第一步之后,对DOM的所有修改都不会引起回流重绘,因为它已经不在渲染树了。
- 隐藏元素,应用修改,重新显示
- 使用文档片段(document fragment)在当前DOM之外构建一个子树,再把它拷贝回文档
- 将原始元素拷贝到一个脱离文档的节点中,修改节点后,再替换原始的元素。
- 现代浏览器会使用队列来储存多次修改,进行优化,所以对这个优化方案,我们其实不用优先考虑。
-
避免触发同步布局事件
当我们访问元素的一些属性的时候,会导致浏览器强制清空队列,进行强制同步布局。在每次循环的时候,都读取了box的一个offsetWidth属性值,然后利用它来更新p标签的width属性。这就导致了每一次循环的时候,浏览器都必须先使上一次循环中的样式更新操作生效,才能响应本次循环的样式读取操作。每一次循环都会强制浏览器刷新队列。
function initP() { for (let i = 0; i < paragraphs.length; i++) { paragraphs[i].style.width = box.offsetWidth + 'px'; } } 复制代码
const width = box.offsetWidth; function initP() { for (let i = 0; i < paragraphs.length; i++) { paragraphs[i].style.width = width + 'px'; } } 复制代码
-
对于复杂动画效果,使用绝对定位让其脱离文档流
-
css3硬件加速(GPU加速)
常见的触发硬件加速的css属性:
- transform
- opacity
- filters
- Will-change
-
7.display: none ,visibility: hidden,opacity:0
-
display:none让元素消失,脱离文档流
-
visibility: hidden让元素隐藏,还在文档流中,占用空间,相当于透明化了
-
opacity:0透明度为0,即完全透明,还在文档流中,占用空间。与visibility: hidden的区别是opacity可设置不同程度的透明度
-
visibility:hidden比display:none性能上要好,display:none切换显示时产生回流,而visibility切换是否显示时则不会引起回流。
8.从输入一个URL到页面渲染流程
一、获取ip地址
- 首先会在浏览器的缓存中查找,是否缓存了URL,如果有,就直接向该URL对应的服务器发送请求;如果没有则进行下一步;
- 在本地的hosts文件中是否保存了该URL和其对应的IP地址,如果保存了,就直接向该URL对应的服务器发送请求;如果没有则进行下一步;
- 向本地DNS服务器(一般由本地网络接入服务器提供商提供,比如移动)发送DNS请求,本地DNS服务器会首先查询它的缓存记录,如果有就将该域名对应的IP地址返回给用户,如果没有则进行下一步;
- 首先向根域名服务器发送DNS查询请求,根域名服务器返回给可能保存了该域名的一级域名服务器地址;本地主机再根据返回的地址,向一级域名服务器发送DNS查询请求;...一直迭代,直到找到对应的域名存放的服务器,向其发送DNS查询请求,该域名服务器返回该域名对应的IP地址;
二、TCP/IP连接
-
三次握手?:如果两次握手,如下面的对话只有前两句,有可能出现的问题是:客户端之前发送了一个连接请求报文,由于网络原因滞留在网络中,后来到达服务器端,服务器接收到该请求,就会建立连接,等待客户端传送数据。而此时客户端压根就不知道发生了什么,白白造成了服务器资源浪费。
相当于:
- 客户端:我要请求数据可以吗?
- 服务器:可以的
- 客户端:好的
三、浏览器向web服务器发送http请求
客户机与服务器建立连接后就可以通信了
- 静态资源:如果客户端请求的是静态资源,则web服务器根据URL地址到服务器的对应路径下查找文件,然后给客户端返回一个HTTP响应,包括状态行、响应头和响应正文。
- 动态资源:如果客户端请求的是动态资源,则web服务器会调用CGI/VM执行程序完成相应的操作,如查询数据库,然后返回查询结果数据集,并将运行的结果--HTML文件返回给web服务器。Web服务器再将HTML文件返回给用户。
四、浏览器渲染
浏览器拿到HTML文件后,根据渲染规则进行渲染:
- 解析HTML,构建DOM树
- 解析CSS,生成CSS规则树
- 合并DOM树和CSS规则树,生成render树
- 布局render树
- 绘制render数、树,即绘制页面像素信息
- GPU将各层合成,结果呈现在浏览器窗口中。
五、四次挥手
客户端没有数据发送时就需要断开连接,以释放服务器资源。
相当于:
- 客户端:我没有数据要发送了,打算断开连接
- 服务器:你的请求我收到了,我这还有数据没有发送完成,你等下
- 服务器:我的数据发送完毕,可以断开连接了
- 客户端:ok,你断开连接吧(客户端独白:我将在2倍的最大报文段生存时间后关闭连接。如果我再次收到服务器的消息,我就知道服务器没有收到我的这句话,我就再发送一遍)。
最终服务器收到该客户端发送的消息断开连接,客户端也关闭连接。
参考链接:
- BFC原理作用https://blog.csdn.net/dff1993/article/details/80394150
- 重绘回流https://www.cnblogs.com/qcloud1001/p/10265985.html
- 输入URL到渲染https://segmentfault.com/a/1190000014311983