• 避免复杂的layout


    layout是浏览器计算元素的几何信息:元素在页面上的的大小和位置。

    每个元素都有明确的亦或含蓄的大小信息,这些信息基于我们使用的css以及元素的内容被高和父亲元素。

    这个过程在 Chrome, Opera, Safari, 和Internet Explorer中叫做Layout.在火狐浏览器中叫做Reflow。

    • Layout的范围是整个文档
    • DOM元素的数量将会影响表现性能:你应该尽可能的禁止触发layout
    • 估计layout模型的性能:新的FlexBox比原来的基于float的layout模型要快的多

    影响layout性能的是:

    1. 需要layout的元素数量
    2. layout的复杂程度

    尽可能避免使用layout

    当你修改样式的时候,浏览器会检查你的修改是否会要求layout被计算,如果有的话讲更新render tree。

    会触发layout的属性都是“几何的属性”,例如: widths, heights, left, or top 等

    .box {
      width: 20px;
      height: 20px;
    }
    
    /**
     * Changing width and height
     * triggers layout.
     */
    .box--expanded {
      width: 200px;
      height: 350px;
    }

    layout作用于整个文档,所以如果有许多的元素的话,将花费很长的时间来计算元素的位置和大小。

    如果不可避免使用layout,那么使用Chrome开发者工具的timeline来追踪查看每个layout的耗费。

    DevTools showing a long time in Layout

    我们可以看见上面我们在layout上面花费了20ms多,如果我们在动画上花费了16ms,那么这个动画就耗费太多资源了。

    你同样可以看见开发者工具总告诉我们树的大小(在上面的情况中有1618个元素),也告诉我们多少节点需要被layout。

    Note

    • 想要一个确切的css属性清单确认哪些属性触发layout,paint和 dimensions ?点击这里:CSS Triggers.

    用flexbox替代老的layout模型

    网络有一系列的layout模型,一些的支持性相对于其他模型支持性更好。

    旧的layout模型允许我们将元素相对定位,亦或绝对定位,亦或float布局在屏幕上。

    下面的截图展示了一个layout(在1300个box上使用float布局)的耗费,这是一个手动的例子,因为现实的应用中我们会使用一系列的定位方式来定位元素。

    Using floats as layout

    如果我们使用FlexBox来定位元素,下面将展示不同:

    Using flexbox as layout

    现在我们在布局上节省了一些时间(例子中3.5msVS14ms),记住上面的对比是作用在相同的元素且产生相同的效果。

    虽然很少的浏览器支持flex布局,但是为了很好的性能,你还是要进行尝试!

    查看flexbox布局支持比float少的文档: less widely supported than floats

    总而言之,不管你使用的浏览器是否支持flexBox,你都应该尽可能的避免触发layout.

    避免强制执行layout

    将帧运输到屏幕上的顺序是下面这样的:

    Using flexbox as layout

    先运行js,之后计算样式,然后layout。

    但是,我们可以强迫浏览器在js之前执行layout。这被叫做强制执行layout。

    首先要知道的是在所有旧的layout上面js可以访问之前帧的任何内容。

    下例中,我们想在帧的开始书写一个元素(让我们把它叫做“盒子”)的高度,我们书写代码如下:

    // Schedule our function to run at the start of the frame.
    requestAnimationFrame(logBoxHeight);
    
    function logBoxHeight() {
      // Gets the height of the box in pixels and logs it out.
      console.log(box.offsetHeight);
    }

    如果我们在js获取盒子高度之前就改变了盒子的高度样式,那么会产生问题:

    function logBoxHeight() {
    
      box.classList.add('super-big');
    
      // Gets the height of the box in pixels
      // and logs it out.
      console.log(box.offsetHeight);
    }

    现在,浏览器为了计算js中的高度问题,浏览器必须先运行样式的改变(因为代码中加入了super-class样式),然后运行layout。只有这样才能返回正确的高度。这是不必要且耗费巨大的工作。

    因为你总是要先读取样式(样式信息保存在之前的帧的layout值中),然后再进行任何的书写操作:

    正确的代码是这样的:

    function logBoxHeight() {
      // Gets the height of the box in pixels
      // and logs it out.
      console.log(box.offsetHeight);
    
      box.classList.add('super-big');
    }

    在大多数情况下你不必要先应用样式然后计算值;使用最后一帧的值将变得绰绰有余。强制layout在js之前运行将会耗费巨大,且浏览器将会进入瓶颈,这是我们不想看到的。

    避免layout thrashing

    比上面强制执行layput更加糟糕的是:连续执行强制layout。

    function resizeAllParagraphsToMatchBlockWidth() {
    
      // Puts the browser into a read-write-read-write cycle.
      for (var i = 0; i < paragraphs.length; i++) {
        paragraphs[i].style.width = box.offsetWidth + 'px';
      }
    }

    每一个循环的时候都将读取box的offWidth的值并且将其赋值给一个paragraph(paragraphs[i].style.width)。在洗一次循环的时候,浏览器会计算已经更改的布局,然后再进行layout,每一个循环都会这样的进行!

    更改之后变得更加可度:

    // Read.
    var width = box.offsetWidth;
    
    function resizeAllParagraphsToMatchBlockWidth() {
      for (var i = 0; i < paragraphs.length; i++) {
        // Now write.
        paragraphs[i].style.width = width + 'px';
      }
    }

    如果你想确保安全性,你可以在 FastDOM网站上检查。该网站好处。。。。你试过就知道了

  • 相关阅读:
    leetcode| Intersection of Two Arrays II
    Spring Boot起步依赖:定制starter
    SpringBoot自动配置的魔法是怎么实现的
    Dubbo中的IoC实现
    必须知道的String知识点
    Dubbo的SPI机制
    为什么要设置HTTP timeout?
    重构代码——简单工厂模式+模板方法模式
    计算机基础——位运算
    系统间HTTP调用代码封装
  • 原文地址:https://www.cnblogs.com/RachelChen/p/5456198.html
Copyright © 2020-2023  润新知