前端进阶版本 ,性能优化—-防抖、节流、重绘与回流

目录

【防抖】

【节流】

重绘(repaint)

回流(reflow):又叫重排(layout)

工作中要如何避免大量使用重绘与回流?

常见的会导致回流的元素


【防抖】

任务频繁触发的情况下,只有任务触发的间隔超过指定间隔的时候,任务才会执行。

/**
 * 防抖函数
 * @author vision
 * @param {执行函数} fn
 * @param {延迟} delay
 */
export function debounce(fn, delay) {
  let timer = null;
  return function() {
    let context = this;
    let arg = arguments;
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(context, arg);
    }, delay);
  };
}

/**
 * 防抖函数 - 箭头函数
 * @param {执行函数} fn
 * @param {延迟} delay
 */
export const debounceEs6 = (fn, delay) => {
  let timer = null;
  return (...rest) => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn(rest);
    }, delay);
  };
};

前端进阶版本 ,性能优化—-防抖、节流、重绘与回流_第1张图片


【节流】

指定时间间隔内只会执行一次任务。


    function throttle(fn) {
      // 通过闭包保存一个标记
      let canRun = true;
      return function() {
        // 在函数开头判断标志是否为 true,不为 true 则中断函数
        if(!canRun) {
          return;
        }
        // 将 canRun 设置为 false,防止执行之前再被执行
        canRun = false;
        // 定时器
        setTimeout( () => {
          fn.call(this, arguments);
          // 执行完事件(比如调用完接口)之后,重新将这个标志设置为 true
          canRun = true;
        }, 1000);
      };
    }

前端进阶版本 ,性能优化—-防抖、节流、重绘与回流_第2张图片


 


重绘(repaint)

当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新,此时由于只需要 UI 层面的重新像素绘制,因此损耗较少。
常见的重绘操作有:

  • 改变元素颜色改变
  • 元素背景色
  • more ……


回流(reflow):又叫重排(layout)

当元素的尺寸、结构或者触发某些属性时,浏览器会重新渲染页面,称为回流。此时,浏览器需要重新经过计算,计算后还需要重新页面布局,因此是较重的操作。
常见的回流操作有:

  • 页面初次渲染
  • 浏览器窗口大小改变
  • 元素尺寸/位置/内容发生改变
  • 元素字体大小变化
  • 添加或者删除可见的 DOM 元素
  • 激活 CSS 伪类(:hover……)
  • more ……

重点:回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高。

169721e0dc217977.png

工作中要如何避免大量使用重绘与回流?

  • 避免频繁操作样式,可汇总后统一一次修改
  • 尽量使用 class 进行样式修改,而不是直接操作样式
  • 减少 DOM 的操作,可使用字符串一次性插入

以下资料来自于 https://juejin.im/post/5e096d63e51d4558381e9906#heading-29

常见的会导致回流的元素

  • 常见的几何属性有 width、height、padding、margin、left、top、border 等等。
  • 最容易被忽略的操作:获取一些需要通过即时计算得到的属性,当你要用到像这样的属性:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight 时,浏览器为了获取这些值,也会进行回流。
  • 当我们调用了 getComputedStyle 方法,或者 IE 里的 currentStyle 时,也会触发回流。原理是一样的,都为求一个“即时性”和“准确性”。

避免方式:

  • 避免逐条改变样式,使用类名去合并样式
  • 将 DOM “离线”,使用DocumentFragment
  • 提升为合成层,如使用will-change
#divId {
  will-change: transform;
}

优点:

  • 合成层的位图,会交由 GPU 合成,比 CPU 处理要快
  • 当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层
  • 对于 transform 和 opacity 效果,不会触发 layout 和 paint

注意:
部分浏览器缓存了一个 flush 队列,把我们触发的回流与重绘任务都塞进去,待到队列里的任务多起来、或者达到了一定的时间间隔,或者“不得已”的时候,再将这些任务一口气出队。但是当我们访问一些即使属性时,浏览器会为了获得此时此刻的、最准确的属性值,而提前将 flush 队列的任务出队。


原文链接:https://blog.csdn.net/jiepan9178/article/details/104264816

你可能感兴趣的:(前端,性能优化)