zoukankan      html  css  js  c++  java
  • 浏览器渲染页面过程

    一、浏览器加载和渲染html的顺序

    1、IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的。
    2、在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都已经下载完)
    3、如果遇到语义解释性的标签嵌入文件(JS脚本,CSS样式),那么此时IE的下载过程会启用单独连接进行下载。
    4、并且在下载后进行解析,解析过程中,停止页面所有往下元素的下载。阻塞加载
    5、样式表在下载完成后,将和以前下载的所有样式表一起进行解析,解析完成后,将对此前所有元素(含以前已经渲染的)重新进行渲染。
    6、JS、CSS中如有重定义,后定义函数将覆盖前定义函数

    二、JS的加载

    1、浏览器对于Javascript的运行有两大特性:1)载入后马上执行,2)执行时会阻塞页面后续的内容(包括页面的渲染、其它资源的下载)。于是,如果有多个js文件被引入,那么对于浏览器来说,这些js文件被被串行地载入,并依次执行。因为javascript可能会来操作HTML文档的DOM树,所以,浏览器一般都不会像并行下载css文件并行下载js文件,因为这是js文件的特殊性造成的。所以,如果你的javascript想操作后面的DOM元素,基本上来说,浏览器都会报错说对象找不到。因为Javascript执行时,后面的HTML被阻塞住了,DOM树时还没有后面的DOM结点。所以程序也就报错了。

    2、当所有样式表都下载完成以后页面才开始一起解析css文件开始渲染文件。

    3、因为浏览器的加载是从上到下一行一行的加载的,所以如果页面同事定义了两个相同命名的js函数,后面的函数会覆盖前面的函数。

    三、HTML页面加载和解析流程

    1.用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件; 
    2.浏览器开始载入html代码,发现<head>标签内有一个<link>标签引用外部CSS文件; 
    3.浏览器又发出CSS文件的请求,服务器返回这个CSS文件; 
    4.浏览器继续载入html中<body>部分的代码,并且CSS文件已经拿到手了,可以开始渲染页面了; 
    5.浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码; 
    6.服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码; 
    7.浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它; 
    8.Javascript脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个<div> (style.display=”none”)。杯具啊,突然就少了这么一个元素,浏览器不得不重新渲染这部分代码; 
    9.终于等到了</html>的到来,浏览器泪流满面…… 
    10.等等,还没完,用户点了一下界面中的“换肤”按钮,Javascript让浏览器换了一下<link>标签的CSS路径; 
    11.浏览器召集了在座的各位<div><span><ul><li>们,“大伙儿收拾收拾行李,咱得重新来过……”,浏览器向服务器请求了新的CSS文件,重新渲染页面。 

    四、 DOMContentLoaded事件

    DOMContentLoaded事件在许多Webkit浏览器以及IE9上都可以使用。
    DOMContentLoaded事件本身不会等待CSS文件、图片、iframe加载完成。
    触发时机:加载完页面,解析完所有标签(不包括执行CSS和JS),并如规范中所说的设置interactive和执行每个静态的script标签中的JS,然后触发。而JS的执行,需要等待位于它前面的CSS加载(如果是外联的话)、执行完成,因为JS可能会依赖位于它前面的CSS计算出来的样式。
     
    现代浏览器会并发的预加载CSS, JS,也就是一开始就并发的请求这些资源,但是,执行CSS和JS的顺序还是按原来的依赖顺序(JS的执行要等待位于其前面的CSS和JS加载、执行完)。先加载完成的资源,如果其依赖还没加载、执行完,就只能等着。
    img是否需要解码、绘图(paint)出来,确实需要等CSS加载、执行完才能知道。也就是说,CSS会阻塞img的展现!那么JS呢?
    在有JS而没有CSS的页面中,img居然能够在收到数据后就立刻开始解码、绘图(paint),也就是说,JS并没有阻塞img的展现!这跟我们以前理解的JS会阻塞img资源的传统观念不太一样,看来Chrome对img的加载和展现做了新的优化。
    执行顺序简单归纳为:
    立即执行函数 =》domReady  =》 onload

    五、js执行时机

    head里的 <script>标签会阻塞后续资源的载入以及整个页面的生成 。所以很多网站把javascript放在网页的最后面,或者动用了window.onload或是docmuemt ready之类事件。
    实现等待DOM被完全加载后才调用JS文件
    1) 将所有的JS文件都放在</HTML>后面后再进行调用
    2 )将JS代码放在标签里面
    Javascript并非完全的按顺序解释执行,而是在解释之前会对Javascript进行一次“预编译”,在预编译的过程中,会把定义式的函数优先执行,也会把所有var变量创建,默认值为undefined,以提高程序的执行效率。当JavaScript引擎解析脚本时,它会在预编译期对所有声明的变量和函数进行处理。

    1. 在执行前会进行类似“预编译”的操作:首先会创建一个当前执行环境下的活动对象,并将那些用var申明的变量设置为活动对象的属性,但是此时这些变量的赋值都是undefined,并将那些以function定义的函数也添加为活动对象的属性,而且它们的值正是函数的定义。

    2. 在解释执行阶段,遇到变量需要解析时,会首先从当前执行环境的活动对象中查找,如果没有找到而且该执行环境的拥有者有prototype属性时则会从prototype链中查找,否则将会按照作用域链查找。遇到var a = ...这样的语句时会给相应的变量进行赋值(注意:变量的赋值是在解释执行阶段完成的,如果在这之前使用变量,它的值会是undefined) 所以,就会出现当JavaScript解释器执行下面脚本时不会报错
    f();  // 调用函数,正确执行
    function f(){ 
       alert(1);
    }
      
    f();// 调用函数,返回语法错误
    var f = function(){
       alert(1);
    }

    上面示例中定义的函数仅作为值赋值给变量f,所以在预编译期,JavaScript解释器只能够为声明变量f进行处理,而对于变量f的值,只能等到执行期时按顺序进行赋值,自然就会出现语法错误,提示找不到对象f。

    JavaScript解释器在执行脚本时,是按块来执行的。通俗地说,就是浏览器在解析HTML文档流时,如果遇到一个<script>标签,则JavaScript解释器会等到这个代码块都加载完后,先对代码块进行预编译,然后再执行。执行完毕后,浏览器会继续解析下面的HTML文档流,同时JavaScript解释器也准备好处理下一个代码块。由于JavaScript是按块执行的,所以如果在一个JavaScript块中调用后面块中声明的变量或函数就会提示语法错误。虽然说,JavaScript是按块执行的,但是不同块都属于同一个全局作用域,也就是说,块之间的变量和函数是可以共享的。

    备注:document.write()会把输出写入到脚本文档所在的位置,浏览器解析完documemt.write()所在文档内容后,继续解析document.write()输出的内容,然后在继续解析HTML文档。
    <script type="text/javascript">//<![CDATA[   
      document.write('<script type="text/javascript" src="test.js"><//script>');
      document.write('<script type="text/javascript">');   
      document.write('alert(2);')   
      document.write('alert("我是" + tmpStr);');   
      document.write('<//script>');    //]]>
    </script> 
    IE下,用Document.Write方法引用js文件时,js文件会出现尚未加载就直接调用的情况,因此建议将引用的JS文件单独放在一个script块中。以确保引用的js文件完全加载后,再继续执行后面的Document.Write内容。在js里出现同名函数后,你在web页面里调用改js函数后,总是调用页面中最后一个加载的函数。

    六、jQuery DomReardy事件

    在Jquery里面,我们可以看到两种写法:$(function(){}) 和$(document).ready(function(){})
    这两个方法的效果都是一样的,都是在dom文档树加载完之后执行一个函数(注意,这里面的文档树加载完不代表全部文件加载完)。
    而window.onload是在dom文档树加载完和所有文件加载完之后执行一个函数。也就是说$(document).ready要比window.onload先执行。

    那么Jquery里面$(document).ready函数的实现:

    document.ready = function (callback) {
      //兼容FF,Google
      if (document.addEventListener) {
         document.addEventListener('DOMContentLoaded', function () {
              document.removeEventListener('DOMContentLoaded', arguments.callee, false);
                    callback();
              }, false)
           }
       //兼容IE
       else if (document.attachEvent) {
           document.attachEvent('onreadytstatechange', function () {
               if (document.readyState == "complete") {
                  document.detachEvent("onreadystatechange", arguments.callee);
                         callback();
                  }
               })
           }
      else if (document.lastChild == document.body) {
              callback();
           }
      }
    
      window.onload = function () {
          alert('onload');
    }; document.ready(function () { alert(
    'ready'); });

    七、 DOM(文档对象模型 Document Object Model)

    参考:

    http://www.kuqin.com/shuoit/20140303/338367.html

    http://www.cnblogs.com/zhangziqiu/archive/2011/06/27/DOMReady.html

    w3c HTML5规范:https://www.w3.org/TR/html5/syntax.html#the-end

    DOMContentLoaded: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded

  • 相关阅读:
    spark streaming 概述
    spark sql 的性能调优
    LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal (用中序和后序树遍历来建立二叉树)
    LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal (用先序和中序树遍历来建立二叉树)
    LeetCode 90. Subsets II (子集合之二)
    LeetCode 88. Merge Sorted Array(合并有序数组)
    LeetCode 81. Search in Rotated Sorted Array II(在旋转有序序列中搜索之二)
    LeetCode 80. Remove Duplicates from Sorted Array II (从有序序列里移除重复项之二)
    LeetCode 79. Word Search(单词搜索)
    LeetCode 78. Subsets(子集合)
  • 原文地址:https://www.cnblogs.com/chenlogin/p/5221562.html
Copyright © 2011-2022 走看看