浏览器渲染HTML的过程和原生JS获取样式
今天来说说
- 浏览器如何渲染HTML
- 如何加快浏览器的渲染速度
- 如何用 JS 获取浏览器样式
1. 首先我们要知道样式是在什么时候被渲染的。浏览器是如何渲染的?
- URL请求对应的资源
- HTML解析文件,并且构建 DOM 树
- 构建DOM的时候 遇到 JS 和 CSS, 控制权转让
- JS解析或者CSS 解析器 解析完当前元素,继续 解析 下个元素,直至 DOM树构建完成
- DOM 树构建完成,浏览器 把 DOM 树的 一些 不可见元素去掉。此后,与 CSS DOM 合成一颗
render
树。 - 浏览器根据这棵 render 树,计算出 各个节点所在屏幕的位置。这个位置叫做 layout,输出layout 树。
- 最后根据 layout 树,将页面 渲染至 屏幕。
A. 为了更好的用户体验,渲染引擎会 尽可能快 的将内容呈现到屏幕上,并不会等到所有的 html 都解析完成采取构建和布局 render 树。(解析一部分,显示一部分,同时,可能还在网络下载其他内容)
B. 因为上面那句话。浏览器 发现了一个 img 标签的请求,向服务器发出请求,此时浏览器不会等图片下载完,而是继续渲染后面的代码。
C. 服务器返回图片文件,由于图片占用了一定面积,影响后面的布局。需要回头重新渲染这部分代码。
D. 为了确保 DOM 树早于 脚本执行,防止 脚本阻塞了 DOM树的构建,页面持续空白。所以,我们通常将script
标签放在页面底部。或者使用window.onload
.
- Reflow(回流):浏览器要花时间去渲染,当它发现了某个部分发生了变化影响了布局,那就需要倒回去重新渲染。
- Repaint(重绘):如果只是改变了某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的repaint,重画某一部分。
Reflow要比Repaint更花费时间,也就更影响性能。所以在写代码的时候,要尽量避免过多的Reflow。
2. 如何加快浏览器的渲染速度,提高 Web 网站的性能呢?
- 减少文件数量。这也是 Webpack 火的原因。JS 都打包成 1个了。css、js合并。
- 减少请求。域名查询、域名解析,也是消耗时间的。
- 使用CDN。原因同上面的原因。
- 页面减肥。删除不必要的空格。 这也是那些 gulp、webpack 插件火的原因。
- 缓存重用数据。
- 指定图像和table的大小。上面说了。浏览器可以立即决定大小的话,就不用等图片请求下载完成后,重新布局。少 回流、回流、回流 reflow。
image 使用 width 和 height。
3. 如何用 JS 获取浏览器样式
首先来介绍一下样式表的种类
- 内嵌样式
- 内部样式
- 外部样式表
网上疯狂查找,一下就出了很多答案。再来看一下张鑫旭大佬有没有写什么有趣的东西。一看,果然有东西,写的还是那么有趣。完美清晰,从鞋子到脚。
A. 采用 window.getComputedStyle
getComputedStyle 是一个可以获取当前元素所有 最终使用的 CSS属性值。返回的是一个 CSS 样式声明对象。
使用语法:const style = window.getComputedStyle("元素", "伪类")
,伪类不存在则使用 null
/ 也可以直接不写。
const oBox = document.querySelector("#box");
const style = window.getComputedStyle(oBox);
console.log(style.height);
注意事项:
- 1.IE8 不兼容。
- 2.只读、不可写。
B. 采用 element.style
能读能写,能屈能伸。
使用语法(不是直接写在内嵌 style 里面的获取不到):
<div id="box" style="height:100px;"></div>
const oBox = document.querySelector("#box");
console.log(oBox.style.height);
注意事项:
- 1.只能获取元素 style 属性里面的样式。内嵌样式、只有内嵌,所以它基本用不上。
C. document.defaultView.getComputedStyle
jQuery源码采用的。
使用方法
const style1 = document.defaultView.getComputedStyle(oBox, null);
const style2 = window.getComputedStyle(oBox, null);
console.log(style1, style2); // 长的差不多
console.log(style1 == style2); // false,有细微的差别
console.log(style1.height === style2.height); // true,获取的样式一致
注意事项:
具体和上面的方法A是一样的。主要原因可能是 不一定平台 用 Windows。
D. element.currentStyle。张鑫旭大佬说的 IE 自娱自乐的属性。 坑爹的 IE 啊。
从作用上来说 getComputedStyle 和 currentStyle 属性走得很近。
使用方法:
看起来好像和 element.style 很像,但是其实两者差很多。
作用上 和 getComputedStyle 一样。不过,currentStyle 没法获取伪类的样式。
var oBox = document.querySelector("#box");
console.log(oBox.currentStyle.height);
坑爹的还不让用 const
。愿我以后不写 IE8 兼容。谢谢上天。
注意事项:
- 不支持伪类样式获取。
一遍一遍的咀嚼,总会烂的。