• 前端性能优化


    渲染优化

    浏览器重绘(Repaint)和回流(Reflow)

    回流必将引起重绘,重绘不一定会引起回流。

    重绘(Repaint)

    当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility 等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

    回流(Reflow)

    当 Render Tree 中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
    会导致回流的操作:

    * 页面首次渲染
    * 浏览器窗口大小发生改变
    * 元素尺寸或位置发生改变元素内容变化(文字数量或图片大小等等)
    * 元素字体大小变化
    * 添加或者删除可见的 DOM 元素
    * 激活 CSS 伪类(例如:hover)
    * 查询某些属性或调用某些方法
    * 一些常用且会导致回流的属性和方法
    clientWidth、clientHeight、clientTop、clientLeftoffsetWidth、offsetHeight、offsetTop、offsetLeftscrollWidth、scrollHeight、scrollTop、scrollLeftscrollIntoView()、scrollIntoViewIfNeeded()、getComputedStyle()、
    getBoundingClientRect()、scrollTo()

    性能影响

    回流比重绘的代价要更高。
    有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。现代浏览器会对频繁的回流或重绘操作进行优化:浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。

    当你访问以下属性或方法时,浏览器会立刻清空队列:

    clientWidthclientHeightclientTopclientLeft
    offsetWidthoffsetHeightoffsetTopoffsetLeft
    scrollWidthscrollHeightscrollTopscrollLeft
    widthheight
    getComputedStyle()
    getBoundingClientRect()
    

    因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。

    如何避免

    CSS

    • 避免使用 table 布局。
    • 尽可能在 DOM 树的最末端改变 class。
    • 避免设置多层内联样式。
    • 将动画效果应用到 position 属性为 absolute 或 fixed 的元素上。
    • 避免使用 CSS 表达式(例如:calc())。

    Javascript

    • 避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。
    // 优化前 const el = document.getElementById('test');
    el.style.borderLeft = '1px';
    el.style.borderRight = '2px';
    el.style.padding = '5px';
    // 优化后,一次性修改样式,这样可以将三次重排减少到一次重排 const el = document.getElementById('test');
    el.style.cssText += '; border-left: 1px ;border-right: 2px; padding: 5px;'
    
    • 避免频繁操作 DOM,创建一个 documentFragment,在它上面应用所有 DOM 操作,最后再把它添加到文档中。
    • 也可以先为元素设置 display: none,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。
    • 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
    • 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。

    交互优化

    防抖(debounce)/节流(throttle)

    防抖(debounce)

    输入搜索时,可以用防抖debounce等优化方式,减少http请求;

    这里以滚动条事件举例:防抖函数 onscroll 结束时触发一次,延迟执行

    function debounce(funcwait) {
      let timeout;
      return function() {
        let context = this; // 指向全局     let args = arguments;
        if (timeout) {
          clearTimeout(timeout);
        }
        timeout = setTimeout(() => {
          func.apply(contextargs); // context.func(args)     }wait);
      };
    }
    // 使用 window.onscroll = debounce(function() {
      console.log('debounce');
    }1000);
    

    节流(throttle)

    节流函数:只允许一个函数在N秒内执行一次。滚动条调用接口时,可以用节流throttle等优化方式,减少http请求;

    下面还是一个简单的滚动条事件节流函数:节流函数 onscroll 时,每隔一段时间触发一次,像水滴一样

    function throttle(fndelay) {
      let prevTime = Date.now();
      return function() {
        let curTime = Date.now();
        if (curTime - prevTime > delay) {
          fn.apply(thisarguments);
          prevTime = curTime;
        }
      };
    }
    // 使用 var throtteScroll = throttle(function() {
      console.log('throtte');
    }1000);
    window.onscroll = throtteScroll;

    VUE 优化建议

    提取组件的 CSS 到单独到文件

    当使用单文件组件时,组件内的 CSS 会以 <style> 标签的方式通过 JavaScript 动态注入。这有一些小小的运行时开销,将所有组件的 CSS 提取到同一个文件可以避免这个问题,也会让 CSS 更好地进行压缩和缓存。

    查阅这个构建工具各自的文档来了解更多:

    优化无限列表性能

    如果你的应用存在非常长或者无限滚动的列表,那么采用 窗口化 的技术来优化性能,只需要渲染少部分区域的内容,减少重新渲染组件和创建 dom 节点的时间。

    vue-virtual-scroll-list 和 vue-virtual-scroller 都是解决这类问题的开源项目。你也可以参考 Google 工程师的文章 Complexities of an Infinite Scroller 来尝试自己实现一个虚拟的滚动列表来优化性能,主要使用到的技术是 DOM 回收、墓碑元素和滚动锚定。

    Google 工程师绘制的无限列表设计

    通过组件懒加载优化超长应用内容初始渲染性能

    上面提到的无限列表的场景,比较适合列表内元素非常相似的情况,不过有时候,你的 Vue 应用的超长列表内的内容往往不尽相同,例如在一个复杂的应用的主界面中,整个主界面由非常多不同的模块组成,而用户看到的往往只有首屏一两个模块。在初始渲染的时候不可见区域的模块也会执行和渲染,带来一些额外的性能开销。

    使用组件懒加载在不可见时只需要渲染一个骨架屏,不需要真正渲染组件

     

    你可以对组件直接进行懒加载,对于不可见区域的组件内容,直接不进行加载和初始化,避免初始化渲染运行时的开销。具体可以参考们之前的专栏文章 性能优化之组件懒加载: Vue Lazy Component 介绍,了解如何做到组件粒度的懒加载。

    代码优化相关

    1、在js中尽量减少闭包的使用
      原因:使用闭包后,闭包所在的上下文不会被释放

    2、在js中避免嵌套循环和"死循环"(一旦遇到死循环,浏览器就会直接卡掉)

    3、在js封装过程中,尽量做到低耦合高内聚。减少页面的冗余代码

    4、css中设置定位后,最好使用z-index改变盒子的层级,让盒子不在相同的平面上

    5、尽量减少使用递归。避免死递归
      解决:建议使用尾递归

    6、在事件绑定中,尽可能使用事件委托,减少循环给DOM元素绑定事件处理函数。

  • 相关阅读:
    git的使用
    本体建模
    word2vec改进之Negative Sampling
    word2vec改进之Hierarchical Softmax
    word2vec原理
    Window下mysql的安装
    PageRank算法
    集成学习-------简单介绍
    自我介绍
    Apollo学习笔记(二):循迹实现过程
  • 原文地址:https://www.cnblogs.com/xikui/p/16191341.html
Copyright © 2020-2023  润新知