天天看點

Web前端性能優化——防抖處理/節流處理/圖檔懶加載前端性能優化

前端性能優化

沒有标準答案,越全面越好,如果做不到,就盡量從前端角度考慮

原則

  • 多使用記憶體,緩存(以空間換時間,這種思想也适用于背景)通路頻繁,變化不大
  • 減少 CPU 計算量,減少網絡加載耗時

入手

1、 提升加載速度

  • 減少資源體積:壓縮代碼(如QQ的圖檔壓縮等)
  • 減少通路次數:合并代碼,SSR服務端渲染、緩存等
  • 使用更快的網絡:CDN
  • CSS 放在 head,JS 放在 body 最下面
  • 盡早開始執行 JS,用 DOMContentLoaded 觸發
  • 懶加載(圖檔懶加載,上滑懶加載)

2、 提升渲染速度

  • 對 DOM 查詢進行緩存
  • 拼單 DOM 操作,合并到一起插入 DOM 結構
  • 節流 throttle 防抖 debounce

防抖

示例:輸入框的 keyup 事件

防抖處理

下面代碼使用定時器對 keyup 事件進行了防抖處理,核心原則就是

  • 當使用者 1000ms 之内沒有再次輸入,就對文本框的内容進行處理(這裡隻是簡單的輸出)
  • 如果使用者在 1000ms 之内繼續輸入,則清除上次的定時器,自然就不會對文本框内容進行處理了
  • 也就是說,最終隻會對最後一次輸入進行處理
  • 試想,如果是實時驗證使用者名是否可用的需求,做了防抖處理後,能夠大大減輕伺服器的壓力,減少請求次數

代碼示範:

<!DOCTYPE html>
<html >

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>防抖</title>
</head>

<body>
  <input type="text" name="" id="userName">

  <script>
    const txt_userName = document.querySelector('#userName')
    txt_userName.addEventListener('keyup', debounce(() => {
      console.log(this);
      console.log(txt_userName.value);
    }))

    // 封裝防抖函數
    function debounce(callback, delay = 1000) {
      let timer = null
      return function () {
        if (timer) {
          // 可取消由 setTimeout() 方法設定的 timeout
          clearTimeout(timer)
        }
        timer = setTimeout(() => {
          // 事件處理代碼
          callback && callback()
          timer = null
        }, delay)
      }
    }
  </script>

</body>

</html>
           

節流

示例:拖拽元素

  • 拖拽元素時,要随時拿到被拖拽元素的位置
  • 直接用 drag 事件,會頻繁觸發,很容易導緻卡頓
  • 節流:無論拖拽速度多快,都會每隔 100ms 觸發一次
<!DOCTYPE html>
<html >

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>節流</title>
  <style>
    .box {
      width: 200px;
      height: 150px;
      background-color: rgb(175, 95, 250);
    }
  </style>
</head>

<body>
  <div class="box" draggable="true"></div>

  <script>
    const box = document.querySelector('.box')
    box.addEventListener('drag', throttling((e) => {
      console.log(e);
    }))
    function throttling(callback, delay=1000) {
      let timer = null
      return function() {
        if(timer) return
        timer = setTimeout(() => {
          callback && callback.apply(this,arguments)
          timer = null
        },delay)
      }
    }
  </script>
</body>

</html>
           

圖檔懶加載

css樣式

<style>
    body {
      width: 100%;
      height: 100%;
    }

    img {
      width: 200px;
      height: 280px;
    }
  </style>
           

html代碼

<body>
  <div>
    <div>
      <h2>白敬亭也太帥了吧</h2>
      <p>今天又是被小白帥炸的一天哦!!!啦啦啦啦啦~~~~~</p>
      <img src="" alt="" src="https://www.77wenyu.com/uploads/img1/20200712/8cf365eed29433fdf0a28882491da083.jpg">
    </div>
    <div>
      <h2>白敬亭也太帥了吧</h2>
      <p>今天又是被小白帥炸的一天哦!!!啦啦啦啦啦~~~~~</p>
      <img src=""
        src="https://star-img.idol001.com/atlas/7177/images/2018/2/6/C58r63d4j41517896392282.jpg/default-w720"
        alt="">
    </div>
    <div>
      <h2>白敬亭也太帥了吧</h2>
      <p>今天又是被小白帥炸的一天哦!!!啦啦啦啦啦~~~~~</p>
      <img src="" alt=""
        src="https://uploadfile.bizhizu.cn/up/92/d4/87/92d487a2c3f10ad62061bfccbbeacff7.jpg.source.jpg">
    </div>
    <div>
      <h2>白敬亭也太帥了吧</h2>
      <p>今天又是被小白帥炸的一天哦!!!啦啦啦啦啦~~~~~</p>
      <img src="" src="https://c-ssl.duitang.com/uploads/item/201803/14/20180314090645_gprdv.jpg" alt="">
    </div>
  </div>
</body>
           

js代碼

<script>
  var imgArr = document.querySelectorAll('img');
  var n = 0; //存儲圖檔加載到的位置,避免每次都從第一張圖檔開始周遊

  // 圖檔懶加載
  function lazyLoad() {
    // 可視區域高度
    const seeHeight = window.innerHeight
    for (var i = n; i < imgArr.length; i++) {
      if (imgArr[i].offsetTop < seeHeight + window.pageYOffset) {
        if (imgArr[i].getAttribute('src') == '') {
          imgArr[i].src = imgArr[i].getAttribute('data-src')
        }
        n = i + 1
      }
    }
  }
  lazyLoad()

  // 滾屏函數
  window.onscroll = throttling(lazyLoad)

  // 節流函數
  function throttling(callback, delay = 1000) {
    let timer = null
    return function () {
      if (timer) return
      timer = setTimeout(() => {
        callback()
        timer = null
      }, delay)
    }
  }
</script>
           

效果如下:

Web前端性能優化——防抖處理/節流處理/圖檔懶加載前端性能優化

繼續閱讀