浏览器渲染页面常见问题

构建过程当中可能会产生的阻塞

  • html的代码,是从上到下一行行执行的,也就是说若是js代码写在head头里,且没有用加在window.onload方法里,那么他是没法读取到body里的标签的。之因此加在window.onload里能够执行,是由于,window.onload里的函数会在dom树加载以后执行。
  • 在遇到link标签后,会在link加载(从服务器下载)完毕后,再执行后续代码。但与此同时,若是还有外部文件,则是同时加载(不阻塞后续外部文件linkscript加载)。可是外部文件内的代码不会执行,只会在代码解析到它的时候执行。
  • script标签会阻塞html解析,由于js可能会改变domcss,所以浏览器会先解析script,避免浪费时间。 要想避免阻塞的话,可以使用deferasync
  • 对于动态建立的link标签不会阻塞其后动态建立的script的加载与执行,无论script标签是否具备async属性。
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>JS Bin</title>
        <script>
            var start = +new Date
        </script>
    
    </head>
    
    <body>
        test
        <script>
            var link = document.createElement('link')
            link.href = 'http://udacity-crp.herokuapp.com/style.css?rtt=2'
            link.rel = 'stylesheet'
            document.head.appendChild(link)
        
            var script = document.createElement('script')
            script.src = 'http://udacity-crp.herokuapp.com/time.js?rtt=1&a'
            document.head.appendChild(script)
        </script>
        <div id="result"></div>
        <script>
            var end = +new Date
            document.getElementById('result').innerHTML = end - start
        </script>
    </body>
    </html>
    复制代码
  • js添加async属性以后,script加载的外部文件成为了异步加载,这时至关于它于本来的html解析过程同步进行。因此他不会被任何加载过程阻塞,只会在本身加载完成以后执行。可是,异步执行的影响就是,它如要读取dom节点,极可能会失败,由于它的加载和html解析过程没有了前后顺序。另外,若是它要输出动态的dom节点,就没法保证节点的位置,由于它添加的节点,是在html已解析的节点下顺序添加的。

    <script src="http://localhost:8080/test.js" async></script>
    复制代码

  • js添加 defer属性以后, script加载的外部文件成为了异步加载,执行是同步的。脚本加载不阻塞页面的解析,脚本在获取完后并不当即执行,而是等到 DOM树加载完毕执行。
    以下代码,加上 defer后会报错 Uncaught ReferenceError: $ is not definedDOM树渲染结束前 body里的 script已经执行了

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>JS Bin</title>
        <script defer src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    </head>
    
    <body>
        <div id="d1">我是内容</div>
        <script >
            console.log($('#d1').html())
        </script>
    </body>
    </html>
    复制代码

什么状况会引发重排/回流(reflow)

  • 添加或者删除可见的DOM元素;
  • 元素位置改变——display、float、position、overflow等等;
  • 元素尺寸改变——边距、填充、边框、宽度和高度
  • 内容改变——好比文本改变或者图片大小改变而引发的计算值宽度和高度改变;
  • 页面渲染初始化;
  • 浏览器窗口尺寸改变——resize事件发生时;

如何减小和避免重排

  • Reflow 的成本比 Repaint 的成本高得多的多。一个节点的 Reflow 颇有可能致使子节点,甚至父节点以及兄弟节点的 Reflow
  • 直接改变className,若是动态改变样式,则使用cssText(考虑没有优化的浏览器)
  • 让要操做的元素进行”离线处理”,处理完后一块儿更新;
    1. 使用DocumentFragment进行缓存操做,引起一次回流和重绘;
    2. 使用display:none技术,只引起两次回流和重绘;
    3. 使用cloneNode(true or false)replaceChild技术,引起一次回流和重绘;
  • 不要常常访问会引发浏览器flush队列的属性,若是你确实要访问,利用缓存;
  • 让元素脱离动画流,减小回流的Render Tree的规模;

DOM是什么?

DOM(Document Object Model——文档对象模型)是用来呈现以及与任意 HTML 或 XML文档交互的API。DOM 是载入到浏览器中的文档模型,以节点树的形式来表现文档,每一个节点表明文档的构成部分(例如:页面元素、字符串或注释等等)。css

DOM的做用

  • DOM 将HTML文档呈现为带有元素、属性和文本的树结构(节点树)。
  • 它容许运行在浏览器中的代码访问文件中的节点并与之交互。节点能够被建立,移动或修改。事件监听器能够被添加到节点上并在给定事件发生时触发。

什么是DOM渲染?

DOM渲染指的是对于浏览器中展示给用户的DOM文档的生成的过程。html

DOM树的构建是文档加载完成开始的?

构建DOM树是一个渐进过程,为达到更好用户体验,渲染引擎会尽快将内容显示在屏幕上。它没必要等到整个HTML文档解析完毕以后才开始构建render数和布局。jquery

Render树是DOM树和CSSOM树构建完毕才开始构建的吗?

这三个过程在实际进行的时候不是彻底独立,而是会有交叉。会形成一边加载,一遍解析,一遍渲染的工做现象。浏览器

相关文章
相关标签/搜索