一、display:none和visibility:hidden的区别
1、display:none隐藏完元素所占据的空间也会消失 。visibility:hidden隐藏完元素还是占据空间。
2、display:none没有继承性,visibility:hidden有继承性。给父元素设置visibility:hidden,其子元素也会继承该属性,如果给子元素设置visibility:visible,则子元素会显示出来。
3、visibility:hidden不会影响计数器的运算,比如ol标签中的li标签,隐藏其中的第二个标签,后续标签的序号不变,而如果使用display:none后续标签的序号会衔接上去上一个。
4、CSS3的transition支持visibility属性,但是并不支持display
5、 display:none会引起回流(重排)和重绘 visibility:hidden会引起重绘
二、提交文档和渲染阶段
1、提交文档
请求回来的文档数据保存在网络进程,还没有提交给渲染进程。在提交文档阶段,浏览器进程将网络进程接收到的HTML数据提交给渲染进程。
具体流程:
1.1、首先当浏览器进程接收到网络进程的响应头数据之后,便向渲染进程发起“提交文档”的消息;
1.2、渲染进程接收到“提交文档”的消息后,会和网络进程建立传输数据的“管道”;等文档数据传输完成之后,渲染进程会返回“确认提交”的消息给浏览器进程;
1.3、浏览器进程在收到“确认提交”的消息后,会更新浏览器界面状态,包括了安全状态、地址栏的 URL、前进后退的历史状态,并更新 Web 页面。
2、渲染阶段
2.1、构建 DOM 树(每个标签对应一个节点,包括display:none被隐藏的节点)
2.2、css解析成样式结构体styleSheets(可以解释成cssom),最后计算得到每个 DOM 节点的样式,并被保存在 ComputedStyle 的结构内。
2.3、构建布局树LayoutTree(可以看成16年之前的渲染树),把所有DOM 树中可见节点添加到布局树中,不可见的节点不会添加到布局树里面( dispaly:none)。
2.4、对布局树进行分层,并生成分层树。
2.5、为每个图层生成绘制列表,并将其提交到合成线程。
2.6、合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图。
2.7、合成线程发送绘制图块命令 DrawQuad 给浏览器进程。
2.8浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。
三、重排、重绘、合成
1、更新了元素的几何属性(重排)
如果你通过 JavaScript 或者 CSS 修改元素的几何位置属性,例如改变元素的宽度、高度等,那么浏览器会触发重新布局,解析之后的一系列子阶段,这个过程就叫重排。无疑,重排需要更新完整的渲染流水线,所以开销也是最大的。
2. 更新元素的绘制属性(重绘)
图中可以看出,如果修改了元素的背景颜色,那么布局阶段将不会被执行,因为并没有引起几何位置的变换,所以就直接进入了绘制阶段,然后执行之后的一系列子阶段,这个过程就叫重绘。相较于重排操作,重绘省去了布局和分层阶段,所以执行效率会比重排操作要高一些。
3. 直接合成阶段
那如果你更改一个既不要布局也不要绘制的属性,会发生什么变化呢?渲染引擎将跳过布局和绘制,只执行后续的合成操作,我们把这个过程叫做合成。具体流程参考下图:避开重排和重绘在上图中,我们使用了 CSS 的 transform 来实现动画效果,这可以避开重排和重绘阶段,直接在非主线程上执行合成动画操作。这样的效率是最高的,因为是在非主线程上合成,并没有占用主线程的资源,另外也避开了布局和绘制两个子阶段,所以相对于重绘和重排,合成能大大提升绘制效率。
四、优化(待研究)
1、浏览器队列优化机制
现代浏览器不会对每次回流重绘都进行操作,而是把涉及回流重绘的操作放到一个队列里面,当一段时间后或者队列放满了后,浏览器会一次性将队列中所有的操作执行,这样就会大大的减少回流重绘的次数,提高性能,但是当代码执行过程中需要获取某些元素的位置信息(比如执行到一些js自带获取位置信息的api时),该队列会被强制刷新,这些api有:offsetLeft,offsetTop, offsetWidth, offsetHeight, clientWidth, clientHeigth,clientLeft,clientTop,scrollWidth, scrollHeight, scrollLeft, scrollTop, getBoundingClientRect()…
2、如何减少回流和重绘
css
使用transform来代替top(css硬件加速,相同效果前者少一个layout延时) 常见的触发硬件加速的css属性:transform,opacity,filters,Will-change 避免使用table布局 尽量避免多层嵌套,结构尽量扁平化 对于有复杂动画效果的DOM元素应该将其独立处出来,脱离文档流 使用visibility,opacity 代替 display: none (前者的展现只涉及重绘, 后者需要回流)
js
给一个DOM元素设置css样式避免一行一行单独设置(如这样: el.style.width = ’40px’, el.style.color = ‘red’), 可以用cssText进行集中设置,或者先把样式类在css设置好,通过js直接加类名。 涉及批量修改DOM可分为三个步骤
(1): 使要修改的DOM元素脱离文档流。
(2): 对其进行多次修改。
(3): 将DOM元素带回文档流。
针对上述的涉及批量修改DOM的方法大概有种如下:
(1)先将元素的display设置为none,然后修改,最后将其重新显示
(2)使用文档片段(createDocumentfragment())在当前文档流外构建一个子树,操作完再将其插入回文档(一般用来涉及DOM元素的增加)
(3)将原始元素拷贝到一个脱离文档的节点中,修改节点后,再替换原始的元素(api: 拷贝 cloneNode(), 替换 replaceChild())
今天的文章display:none和visibility:hidden的区别,引发重排、重绘、合成阐述分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18587.html