我有这么一段代码:
这是html <button id="btn">死循环</button> <div class="ball ball1"></div> <div class="ball ball2"></div>这是js function delay(duration) { var start = Date.now(); while (Date.now() - start < duration) {} } btn.onclick = function () { delay(5000); };这是css .ball { width: 100px; height: 100px; background: #f40; border-radius: 50%; margin: 30px; } .ball1 { animation: move1 1s alternate infinite ease-in-out; } .ball2 { position: fixed; left: 0; animation: move2 1s alternate infinite ease-in-out; } @keyframes move1 { to { transform: translate(100px); } } @keyframes move2 { to { left: 100px; } }可以在将上述代码运行一次,点击按钮,看一下两个球的状态。 为什么在死循环的时候一个在动,一个不动呢? 从这个问题着手,我们先不看问题,先来看标题,为什么这个和浏览器渲染有关系? 书接上回,不知道上回是哪儿的点击这里。 我们说浏览器的渲染进程里边主要的渲染主线程很繁忙,有很多工作要做,要解析HTML、CSS、进行样式计算、执行全局js、执行事件处理函数等。第一个是解析HTML对吧。所以渲染主线程有个很主要的工作,渲染。 首先说一下渲染的步骤: 1、解析HTML。 2、进行样式计算。 3、布局。 4、分层。 5、绘制。 6、光栅化。 7、画。 咱们逐一讲解: 解析HTML 我们在浏览器的任何一个页面上鼠标右键点击查看页面源代码的时候会看到一大段一大段的东西,我们有没有想过这是什么?这是不是一大段的字符串呢?是的,它是!那么该怎么办呢? 浏览器在解析HTML之前会先启动预解析现成。会率先下载外部css和外部js。 我们一直听说过浏览器执行是从上到下执行,所以浏览器在解析的时候,如果碰到link,如果css没下载好则会将其扔进消息队列下载进行其他的处理工作,所以css不会阻塞html解析。但是js不一样,碰到script标签会等待js执行完成再继续进行html解析,因为可能会在js中产生修改当前dom树的操作。 这里说到了一个词叫做dom树,html解析其实就是将代码逐一解析,解析成dom树和cssom树,浏览器的默认样式、内部样式、外联样式、行内样式都在cssom中。引申一下,浏览器的默认样式在哪儿,为什么p标签和div标签会默认独占一行,为什么span标签不会?这些是因为在浏览器源码中对p和div都是display:block的。 样式计算 样式计算其实就是在这一步里,浏览器会去循环遍历dom树,将dom树和它的每个节点的样式计算出来生成一颗带有样式的dom树。在这里会将很多数值从相对数值变成绝对数值。我们在浏览器的调试工具里可以找到,在页面右击--检查--元素--样式--中文是以计算,应为是computed里边。你可以试试设置样式color为red,computed里边会是rgb颜色。 布局 布局也会遍历dom树,不过是样式计算后的dom树,遍历到每一个节点,根据样式生成每个节点的几何信息。 布局树会和dom树一致吗?一般不会一致的。因为譬如display:none这种隐藏的节点是找不到几何信息的。所以在布局树中不会有他的信息。 分层 渲染主线程有复杂的策略进行分层,浏览器的分层目的是分成一个个层以后,如果某个层改变指挥重新处理该层,提高浏览器的工作效率,这个分层在浏览器中是看得到的。在浏览器--检查--3d视图里边,如果找不到可以在加号中找到。 绘制 绘制其实已经离出现内容在浏览器上比较近了,绘制是将分层的结果生成指令集,告诉应该怎么进行画出来。 在完成绘制之后,渲染主线程就会将绘制信息交给合成线程,从这里其就离开了主线程。合成线程会对图层进行分块,这里不会是一个线程完成这部分的工作,而是从线程池中拿取多个线程进行工作。 光栅化 合成线程将分块信息交给浏览器的GPU进程来进行光栅化得到位图,靠近视口的优先。 画 这里已经是最后一步了,合成线程拿到光栅化以后的一个个位图,会生成指引信息,指引信息指出每个位图在浏览器的哪些地方,有没有旋转缩放等变形操作。所以在这里我们看到了变形其实发生在最后的合成线程,它和最开始的样式计算没有关系,它与渲染主线程没有关系,所以transform会效率比设置left这些属性效率更高。因为它不影响布局,不影响绘制这些,指挥再画的时候产生效果。他不会影响到渲染主线程,所以,渲染主线程就算忙碌也不会影响transform。 |
|