日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

关于前端性能优化问题,认识网页加载过程和防抖节流

發布時間:2023/12/4 HTML 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于前端性能优化问题,认识网页加载过程和防抖节流 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前端性能優化—網頁加載過程、性能優化方法、防抖和節流

  • 一、網頁加載過程
    • 1、加載資源的形式
    • 2、加載資源的過程
    • 3、渲染頁面的過程
    • 4、關于window.onload 和 DOMContentLoaded
  • 二、性能優化
    • 1、性能優化原則
    • 2、性能優化的方法
    • 3、讓加載更快
    • 4、讓渲染更快
  • 三、防抖和節流
    • 1、防抖 debounce
    • 2、節流 throttle
  • 四、寫在最后

平常我們在加載網頁的時候,首先需要先加載網頁代碼,之后渲染出頁面,在這個期間會執行若干個 JS 。那么,如果想要讓網頁呈現速度和渲染速度快,我們就得保證我們的代碼在瀏覽器這個運行環境當中穩定且高效。這就談到一個前端性能優化的問題。

在下面這篇文章,將講解關于前端性能優化的一些常見問題。

一、網頁加載過程

1、加載資源的形式

網頁需要加載的資源,一般包括以下內容:

  • html 代碼;
  • 媒體文件,如圖片、視頻等;
  • javascript、 css 。

2、加載資源的過程

加載資源的過程需要經過以下幾個步驟:

  • DNS 解析:域名 -> IP 地址。
  • 瀏覽器根據 IP 地址向服務器發起 http 請求。
  • 服務器處理 http 請求,并返回給瀏覽器。

3、渲染頁面的過程

渲染過程 - 1

  • 根據 HTML 代碼生成 DOM Tree ;
  • 根據 CSS 代碼生成 CSSOM ;
  • 將 DOM Tree 和 CSSOM 整合形成 Render Tree 。

渲染過程 - 2

  • 根據 Render Tree 渲染頁面;
  • 遇到 <script> 則暫停渲染,優先加載并執行 JS 代碼,完成后再繼續執行;
  • 直至把 Render Tree 渲染完成。

4、關于window.onload 和 DOMContentLoaded

window.addEventListener('load', function(){//頁面的全部資源加載完才會執行,包括圖片、視頻等 });document.addEventListener('DOMContentLoaded', function(){//DOM 渲染完即可執行,此時圖片、視頻還可能沒加載完 -> 盡量選擇此方法 });

二、性能優化

性能優化是一個綜合性的問題,永遠沒有標準答案,下面將從幾個方面來講解性能優化的內容。

1、性能優化原則

  • 多使用內存、緩存或其他方法。
  • 減少 CPU 計算量,減少網絡加載耗時。
  • 適用于所有編程的優化方法 —— 空間換時間。

2、性能優化的方法

(1) 讓加載更快

(2) 讓渲染更快

3、讓加載更快

(1)減少資源體積

  • 壓縮代碼: 可以通過壓縮代碼來減少資源體積,包括 js 文件、 css 文件和圖片都可以進行壓縮。同時服務器端 可以通過 gzip 算法來對資源進行壓縮。

(2)減少訪問次數

  • 合并代碼: 比如說我們寫了三四個文件,但通過打包可能就只剩下一個文件,并且文件里面是以一行的形式出現,或者雪碧圖也算是其中一種方式。

  • SSR服務器端渲染:

    服務端把網頁和數據一起加載,一起渲染。

    非SSR:先加載網頁,再加載數據,再渲染數據,這個過程聽起來就優點繁瑣。

    早期的 JSP 、ASP 、PHP,現在的 vue SSR 、React SSR。

  • 緩存:

    舉個例子:假設有 10 個資源,如果每次請求都要請求 10 次,那這樣子是非常耗時的;那如果 10 個資源中有 6 個命中了緩存,則只需要請求另外 4 個。

    那如何做緩存來達到減少訪問次數呢?

    前端會在靜態資源上加 hash 后綴,根據文件內容計算 hash 。當文件內容不變時,則 hash 和 url 都不變。此時 url 和文件不變,則會自動觸發 http 緩存機制,返回 304 。

(3)使用更快的網絡

  • 通過 CDN 來操作:

    CDN ,即內容分發網絡(Content Delivery Network,簡稱 CDN ),是建立并覆蓋在承載網之上,由分布在不同區域的邊緣節點服務器群組成的分布式網絡。

    CDN 就是一個反向代理,根據地域來做網絡服務,主要是前端用來做靜態資源加載,通常在前端項目部署的時候進行這項操作。

    我們平常所使用的 bootstrap 、 JQuery 一般都采用 cdn 的形式。

    這里我也不是特別了解 cdn 的內容,只能才疏學淺的進行介紹。附上一篇我看完覺得比較好理解的文章,大家可以根據需求進行查看~

4、讓渲染更快

(1)html、css、js和圖片層面

  • css 放在 head , JS 放在 body 最下面;

  • 盡早開始執行 JS ,用 DOMContentLoaded 觸發;

  • 懶加載(圖片懶加載,上滑加載更多)。

    <img id = "img1" src = "preview.png" data-realsrc = "abe.png"/> <script type = "text/javascript">let img1 = document.getElementById('img1');//把真實的圖片data-realsrc賦值給預覽的圖片srcimg1.src = img1.getAttribute('data-realsrc');//…… 一系列邏輯操作 </script>

(2)從DOM層面

  • 對 DOM 查詢進行緩存;
  • 從頻繁進行 DOM 操作,變為合并到一起進行 DOM 結構插入;

注:關于DOM的性能優化我有在之前的一篇文章中講過,在主題一的第4小點,這里不再進行細講,大家可以根據自身需求進行查閱~

(3)防抖 debounce 和 節流 throttle

關于防抖和節流的講解,詳細見下方。

三、防抖和節流

1、防抖 debounce

(1)含義: 從頻繁執行觸發變為只在最后一次觸發。

(2)發生場景: 監聽一個輸入框,如果直接用 keyup 事件,則每輸入一個文字都會觸發 onchange 事件,頻繁執行操作。

(3)防抖解決: 用戶輸入結束或暫停時,才會觸發 change 事件。

(4)引例闡述

假設我們現在要監聽一個輸入框的值,此時我們直接用 keyup 事件來實現。實現方式如下:

<!DOCTYPE html> <html lang="en"> <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>Document</title> </head> <body><input type="text" id="input1"><script type="text/javascript">const input1 = document.getElementById('input1');input1.addEventListener('keyup', function(){console.log(input1.value);});</script> </body> </html>

此時瀏覽器的顯示效果是這樣的。

大家可以發現,當我們使用 keyup 事件處理,每當我們輸入一個字母時,瀏覽器就會頻繁進行打印,這樣看起來也太耗費性能了。

于是就有了防抖的解決方案,防抖通過對頻繁執行的操作變為只在最后一次執行。實現方式如下:

<!DOCTYPE html> <html lang="en"> <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>Document</title> </head> <body><input type="text" id="input1"><script type="text/javascript">const input1 = document.getElementById('input1');let timer = null;input1.addEventListener('keyup', function(){if(timer){clearTimeout(timer);}timer = setTimeout(() => {//模擬觸發 change 事件console.log(input1.value);//清空定時器timer = null;}, 500);// console.log(input1.value);});</script> </body> </html>

此時瀏覽器的顯示效果是這樣的。

通過上圖發現,當我們在輸入框輸入字母時,只在最后輸入結束時控制臺才打印結果出來。而不會像上面那樣頻繁打印,因此通過防抖,實現了把頻繁執行變為了只在最后一次執行的操作。

(5)封裝防抖函數

通過上面的例子,相信大家對防抖有了一個基礎的了解。接下來我們通過封裝函數來實現相同效果的防抖功能。具體代碼如下:

<!DOCTYPE html> <html lang="en"> <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>Document</title> </head> <body><input type="text" id="input1"><script type="text/javascript">const input1 = document.getElementById('input1');// 封裝一個防抖函數function debounce(fn, delay = 500){// timer 是在閉包中的let timer = null;return function(){if(timer){clearTimeout(timer);}timer = setTimeout(() => {fn.apply(this, arguments);}, delay);}}//運用防抖函數實現input輸入框觸發操作input1.addEventListener('keyup', debounce(function () {console.log(input1.value);}, 600));</script> </body> </html>

2、節流 throttle

(1)含義: 從頻繁執行觸發變為每隔一段時間觸發一次。

(2)發生場景: 拖拽一個元素時,直接用 drag 事件,則會頻繁觸發,很容易導致卡頓。

(3)節流解決: 無論拖拽速度多快,都會每隔 100ms 觸發一次(這里的 100ms 不是固定值,也可設置成其它的值)。

(4)引例闡述

假設我們現在要拖拽一個元素,并且想要隨時拿到該元素被拖拽的值。此時我們直接用 drag 事件來實現。實現方式如下:

<!DOCTYPE html> <html lang="en"> <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>Document</title><style>#div1{border: 1px solid #ccc;width: 200px;height: 100px;}</style> </head> <body><div id = "div1" draggable="true">可拖拽</div><script type="text/javascript">const div1 = document.getElementById('div1');//用節流之前div1.addEventListener('drag', function(e) {console.log(e.offsetX, e.offsetY);})</script> </body> </html>

此時瀏覽器的顯示效果是這樣的。

大家可以發現,當我們使用 drag 事件處理,每當我們拖拽元素時,瀏覽器就會頻繁進行打印,這樣似乎有一點點耗費性能。

于是就有了節流的解決方案,節流通過對頻繁執行的操作變為只在每隔一段時間操作。實現方式如下:

<!DOCTYPE html> <html lang="en"> <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>Document</title><style>#div1{border: 1px solid #ccc;width: 200px;height: 100px;}</style> </head> <body><div id = "div1" draggable="true">可拖拽</div><script type="text/javascript">const div1 = document.getElementById('div1');// 用節流之后let timer = null;div1.addEventListener('drag', function(e){if(timer){return;}timer = setTimeout(() => {console.log(e.offsetX, e.offsetY);timer = null;}, 500);});</script> </body> </html>

此時瀏覽器的顯示效果是這樣的。

通過上圖發現,當我們在拖拽時,不再像剛剛那樣頻繁打印,而是有規律的每隔 500ms 打印一次,這樣子看起來就比剛剛的頻繁觸發要好很多了。所以,節流是通過將頻繁執行改為每隔一段時間執行。

(5)封裝節流函數

通過上面的例子,相信大家對節流有了一個基礎的了解。接下來我們通過封裝函數來實現相同效果的節流功能。具體代碼如下:

<!DOCTYPE html> <html lang="en"> <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>Document</title> </head> <body><input type="text" id="input1"><script type="text/javascript">const input1 = document.getElementById('input1');// 封裝一個節流函數function throttle(fn, delay = 500){let timer = null;return function (){if(timer){return;}timer = setTimeout(() => {fn.apply(this, arguments);timer = null;}, delay);}}//運用節流函數實現拖拽時每隔一段時間觸發操作div1.addEventListener( 'drag', throttle(function(e){console.log(e.offsetX, e.offsetY);}, 200));</script> </body> </html>

四、寫在最后

關于前端性能優化的一些基礎內容就講到這里啦!如有疑問或文章有講的不好的地方歡迎評論區評論或私信我交流~

  • 關注公眾號 星期一研究室 ,不定期分享學習干貨

  • 如果這篇文章對你有用,記得點個贊加個關注再走哦~

總結

以上是生活随笔為你收集整理的关于前端性能优化问题,认识网页加载过程和防抖节流的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。