浏览器解析html与渲染顺序问题

谷歌(版本 55.0.2883.87 m),火狐(48.0.2),ie(11.576.14393.0)对三个浏览器简单的进行了一下试验发现。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>浏览器测试</title>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1">
    <style>
        .box1{
            color:red;
            }
    </style>
  </head>
  <body>
     <div class="box1">1啊222333是</div>
      <div class="box1">1啊是sd第三方s的士大夫f444速度啊分士大夫2222</div>
      <div class="box1">1啊是sd第三方s的士大夫f速度啊分士大夫222</div>
      <div class="box1">1啊是sd第三方s的士的士大2222夫士大夫大夫f速度啊分士大夫</div>
      <script>
            alert(1);
        </script>
  </body>
<html>

谷歌浏览器

clipboard.png
火狐浏览器

clipboard.png
ie11

clipboard.png

出现这种情况,我的理解是谷歌浏览器是等到html全部解析完毕之后才开始渲染,而另外两款浏览器则是边解析边渲染。
然而,当把script里面的js代码从alert换成

var time=+new Date();
    while(true){
        if(+new Date()-time>3000){
            break;
            }
        }

时候发现,三款浏览器都需要经过3秒延迟之后才进行页面渲染更新。
我的问题是,为什么这段延迟代码和上面的通过alert实现的阻塞 两者在页面渲染结果不一样?

阅读 5.2k
3 个回答

经过一段测试发现如下结果。
首先是谷歌浏览器。
谷歌浏览器在首次渲染的时候,是等到html全部解析完毕之后才进行页面的渲染,而进行页面刷新操作的时候,谷歌浏览器会对html进行边解析边渲染,但是需要解析一定数量的dom.
测试如下图。
测试代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>浏览器测试</title>
    <meta name="viewport" content="initial-scale=1, maximum-scale=1">
    <style>
        .box1{
            color:red;
            }
    </style>
  </head>
  <body>
    <div class="box1">我是天才</div>
    <div class="box1">1啊是sd第三方s的士大夫f444速度啊分士大夫2222</div>
    <div class="box1">1啊是sd第三方s的士大夫f速度啊分士大夫222</div>
    <div id='haha'>1啊是sd第三方s的士的士大2222夫士大夫大夫f速度啊分士大夫</div>
    <script> 
            var time=+new Date();
            while(true){
                if(+new Date()-time>3000){
                    break;
                    }
                }
      </script>
  </body>
<html>

通过谷歌浏览器的timeline调试工具发现,此时在解析html时并未进行渲染(解析dom数量并未达到一定程度)
在html解析完成之后才进行渲染,
所以大致过程是html解析-->(解析代码数量少不进行渲染)-->遇到(alert或者死循环)-->阻塞-->阻塞结束,渲染页面

clipboard.png

clipboard.png

而增加HTML代码中的div数量到一定程度时候,在观察timeline发现,当html解析一定程度时就会进行一次渲染
html解析-->(解析代码数量够)-->渲染一部分html-->遇到(alert或者死循环)-->阻塞-->阻塞结束,继续渲染

clipboard.png

clipboard.png
而此次测试使用的firefox和ie11浏览器,对于while(true)的表现是
html解析-->遇到js-->终止渲染-->(死循环)-->循环结束,继续渲染
并未出现边解析变渲染的效果(也就是不管在js之前html解析了多少也不会进行渲染)
而两款浏览器对alert则进行了优化,alert并不会阻断渲染。

在我电脑上测试,第一段代码在所有浏览器中都是一致的,所以跟楼主说的在谷歌不渲染有点不一样。

下面是正文:

通常是在请求JS文件的时候,浏览器才会判断DOM上是否能够渲染出来。这里面用到的两种都是内嵌的JS代码执行。JS代码的执行的时候,页面是不会被重新渲染的,也就是说会阻塞。第二段代码是一个大于3秒的循环操作,因此这个时候,页面是会被阻塞不会渲染的。

至于alter,这个比较特殊,因此执行JS的时候,alter后面的代码并不会被执行,因此这个时候一些浏览器可以做出优化,将DOM中可以渲染的都渲染到页面。这个就解释了alter渲染的问题。

因此边解析边渲染虽然可以这么做,但好像很多浏览器都没有这么实现。文中所做的测试只是符合alter的优化条件而已。

我的谷歌浏览器是是5.0的,效果文中其他两个浏览器是一致的。至于为什么5.5的不会显示,我没有下载测试过这里不好评论。不过我觉得可能是对alter的优化条件进行改变了吧。

1、我觉得应该是浏览器对alert的实现不同

有可能FF和ie的实现是长这样的:

UI解析代码
...

(遇到alert)

UI渲染主要代码
...

alert()

UI渲染后续代码
...

而chrome的实现长这样:

UI解析代码
...

(遇到alert)

alert()

UI渲染主要代码
...

UI渲染后续代码
...

2、死循环强行阻塞
在FF和IE中可能是这样的:
文档从上往下开始解析,遇到script解析执行脚本,进入死循环,阻塞渲染,但是仍然继续往下解析直到不再阻塞渲染时开始渲染。
在chrome中可能是这样的:
文档从上往下开始解析,遇到script解析执行脚本,进入死循环,阻塞渲染,但是不往下解析,直到循环结束,开始渲染并且继续往下解析。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题