利用MutationObserver實(shí)現(xiàn)計(jì)算首屏?xí)r間
一、前言
在前端開(kāi)發(fā)中,優(yōu)化頁(yè)面性能是至關(guān)重要的,計(jì)算首屏?xí)r間(First Contentful Paint,F(xiàn)CP)是衡量網(wǎng)頁(yè)性能的重要指標(biāo),它表示頁(yè)面內(nèi)容中的第一個(gè)元素被渲染到屏幕上的時(shí)間點(diǎn)。而MutationObserver是一種強(qiáng)大的JavaScript API,可以用于監(jiān)聽(tīng)DOM的變化,并幫助開(kāi)發(fā)者計(jì)算首屏?xí)r間,即頁(yè)面加載后第一次渲染完畢的時(shí)間點(diǎn)。本文將介紹如何使用MutationObserver來(lái)獲取首屏?xí)r間的最佳實(shí)踐,并提供具體的原理分析、代碼示例以及其他應(yīng)用場(chǎng)景。
二、原理分析
MutationObserver利用了瀏覽器的MutationObserver接口來(lái)監(jiān)聽(tīng)DOM的變化。當(dāng)DOM樹(shù)中的元素發(fā)生變化時(shí),MutationObserver會(huì)自動(dòng)觸發(fā)注冊(cè)的回調(diào)函數(shù)。通過(guò)在回調(diào)函數(shù)中記錄時(shí)間戳,可以計(jì)算出首屏?xí)r間,即頁(yè)面加載后第一次渲染完畢的時(shí)間點(diǎn)。
1.創(chuàng)建MutationObserver對(duì)象:通過(guò)構(gòu)造函數(shù)MutationObserver創(chuàng)建一個(gè)MutationObserver對(duì)象,并傳入一個(gè)回調(diào)函數(shù)作為參數(shù)。
2.配置MutationObserver:通過(guò)MutationObserver的配置選項(xiàng),指定需要監(jiān)測(cè)的DOM樹(shù)變化類(lèi)型。常見(jiàn)的配置選項(xiàng)有:
childList:是否監(jiān)測(cè)子節(jié)點(diǎn)的變化,即DOM元素的添加或刪除。attributes:是否監(jiān)測(cè)屬性的變化,比如元素的屬性值發(fā)生變化。characterData:是否監(jiān)測(cè)字符數(shù)據(jù)的變化,比如文本節(jié)點(diǎn)的內(nèi)容發(fā)生變化。subtree:是否監(jiān)測(cè)整個(gè)DOM子樹(shù)的變化,包括子節(jié)點(diǎn)及其后代節(jié)點(diǎn)的變化。
3.觀察DOM樹(shù):將MutationObserver對(duì)象與需要觀察的目標(biāo)節(jié)點(diǎn)(通常是文檔對(duì)象document)關(guān)聯(lián)起來(lái),開(kāi)始監(jiān)測(cè)DOM樹(shù)的變化。
observer.observe(targetNode, observerConfig);
4.監(jiān)測(cè)DOM樹(shù)變化:一旦MutationObserver開(kāi)始觀察,它會(huì)監(jiān)測(cè)指定的DOM樹(shù)變化類(lèi)型。當(dāng)DOM樹(shù)發(fā)生符合指定類(lèi)型的變化時(shí),會(huì)觸發(fā)回調(diào)函數(shù),并將變化的信息傳遞給回調(diào)函數(shù)作為參數(shù)。
function callback(mutationsList, observer) {
// 處理DOM樹(shù)的變化
}在回調(diào)函數(shù)中,我們可以遍歷mutationsList,檢查DOM樹(shù)的變化情況,然后根據(jù)需要執(zhí)行相應(yīng)的操作。比如,找到首屏元素并記錄首屏?xí)r間,或者處理其它DOM樹(shù)的變化情況。
5.停止觀察:在需要停止觀察DOM樹(shù)變化時(shí),我們可以調(diào)用disconnect()方法來(lái)停止MutationObserver的觀察。
observer.disconnect();
三、最佳實(shí)踐
1.初始化MutationObserver監(jiān)聽(tīng): 在頁(yè)面加載后,通過(guò)JavaScript代碼創(chuàng)建一個(gè)MutationObserver對(duì)象,并注冊(cè)一個(gè)回調(diào)函數(shù)。回調(diào)函數(shù)會(huì)在DOM樹(shù)中的元素發(fā)生變化時(shí)自動(dòng)觸發(fā)。
const observer = new MutationObserver(callback);
observer.observe(document, {
childList: true, // 監(jiān)測(cè)子節(jié)點(diǎn)的變化(元素的添加或刪除)
subtree: true // 監(jiān)測(cè)子樹(shù)的變化(深層元素的修改)
});2.計(jì)算DOM變化時(shí)的時(shí)間: 在回調(diào)函數(shù)中,可以通過(guò)檢查DOM元素的變化來(lái)判斷頁(yè)面是否已經(jīng)渲染完畢。例如,可以檢查頁(yè)面中某個(gè)元素的可見(jiàn)性、位置或樣式等屬性是否發(fā)生變化,從而判斷頁(yè)面的渲染狀態(tài)。
function callback(mutationsList) {
let firstScreenTime = 0;
mutationsList.forEach(mutation => {
// 檢查DOM元素的變化
if (mutation.type === 'attributes' && mutation.attributeName === 'style' && !document.querySelector('.loading').style.display) {
// 頁(yè)面首屏渲染完畢
firstScreenTime = performance.now();
}
});
if (firstScreenTime > 0) {
console.log(`首屏?xí)r間:${firstScreenTime}ms`);
// 可以在這里執(zhí)行首屏渲染完畢后的操作
}
}3.去掉DOM被刪除情況的監(jiān)聽(tīng): 在回調(diào)函數(shù)中,MutationObserver會(huì)監(jiān)聽(tīng)到DOM樹(shù)中元素的添加、刪除、屬性變化等多種變化。但在計(jì)算首屏?xí)r間時(shí),只關(guān)注DOM的添加和屬性變化即可,因此可以在回調(diào)函數(shù)中去掉對(duì)DOM被刪除的情況的監(jiān)聽(tīng),從而避免不必要的性能開(kāi)銷(xiāo)
function callback(mutationsList) {
let firstScreenTime = 0;
mutationsList.forEach(mutation => {
// 只關(guān)注DOM元素的添加和屬性變化
if ((mutation.type === 'attributes' && mutation.attributeName === 'style') || mutation.type === 'childList') {
// 檢查DOM元素的變化
// 你可以在這里根據(jù)項(xiàng)目需要查找首屏元素的特定條件,比如特定的CSS類(lèi)或ID
if (!document.querySelector('.loading').style.display) {
// 頁(yè)面首屏渲染完畢,首屏元素被找到,記錄首屏?xí)r間
firstScreenTime = performance.now();
// 停止觀察,避免重復(fù)計(jì)算首屏?xí)r間
observer.disconnect();
}
}
});
if (firstScreenTime > 0) {
console.log(`首屏?xí)r間:${firstScreenTime}ms`);
// 可以在這里執(zhí)行首屏渲染完畢后的操作
}
}四、其他應(yīng)用場(chǎng)景
- 動(dòng)態(tài)表單驗(yàn)證:在表單中添加MutationObserver,實(shí)時(shí)監(jiān)測(cè)用戶(hù)輸入的變化,根據(jù)用戶(hù)輸入的內(nèi)容進(jìn)行實(shí)時(shí)的表單驗(yàn)證,提供即時(shí)的錯(cuò)誤提示和反饋。
- 圖片懶加載:對(duì)于圖片懶加載技術(shù),可以使用MutationObserver來(lái)監(jiān)測(cè)圖片元素是否進(jìn)入了可視區(qū)域,從而在圖片出現(xiàn)在可視區(qū)域內(nèi)時(shí)才加載圖片資源,減少頁(yè)面的初始加載時(shí)間和帶寬消耗。
- 無(wú)障礙輔助功能:通過(guò)MutationObserver監(jiān)測(cè)頁(yè)面內(nèi)容的變化,可以實(shí)現(xiàn)輔助功能,比如在內(nèi)容動(dòng)態(tài)更新時(shí)提供適當(dāng)?shù)钠聊婚喿x器提示。
- 防止修改/刪除水印圖片或文字,當(dāng)觸發(fā)了水印元素的MutationObserver回調(diào)的時(shí)候,不去做具體的判斷和恢復(fù)邏輯,而是將這個(gè)水印div刪掉并重新生成新的水印div。
到此這篇關(guān)于利用MutationObserver實(shí)現(xiàn)計(jì)算首屏?xí)r間的文章就介紹到這了,更多相關(guān)MutationObserver計(jì)算首屏?xí)r間內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript數(shù)組之展開(kāi)運(yùn)算符詳解
這篇文章主要給大家介紹了關(guān)于JavaScript數(shù)組之展開(kāi)運(yùn)算符的相關(guān)資料,你可以通過(guò)展開(kāi)操作符(Spread operator)擴(kuò)展一個(gè)數(shù)組對(duì)象和字符串,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
使用原生JS實(shí)現(xiàn)移動(dòng)端購(gòu)物車(chē)效果案例
原生JavaScript作為前端開(kāi)發(fā)的基石,在構(gòu)建交互式網(wǎng)頁(yè)應(yīng)用中扮演著至關(guān)重要的角色,下面這篇文章主要介紹了使用原生JS實(shí)現(xiàn)移動(dòng)端購(gòu)物車(chē)效果案例的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2026-02-02
IE瀏覽器下JS腳本提交表單后,不能自動(dòng)提示問(wèn)題解決方法
這篇文章主要介紹了IE瀏覽器下JS腳本提交表單后,不能自動(dòng)提示問(wèn)題解決方法,涉及IE瀏覽器配置與javascript事件處理操作技巧,需要的朋友可以參考下2019-06-06
如何將HTML字符轉(zhuǎn)換為DOM節(jié)點(diǎn)并動(dòng)態(tài)添加到文檔中詳解
這篇文章主要給大家介紹了關(guān)于如何將HTML字符轉(zhuǎn)換為DOM節(jié)點(diǎn)并動(dòng)態(tài)添加到文檔中的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧2018-08-08
JavaScript 產(chǎn)生不重復(fù)的隨機(jī)數(shù)三種實(shí)現(xiàn)思路
在 JavaScript 中,一般產(chǎn)生的隨機(jī)數(shù)會(huì)重復(fù),但是有時(shí)我們需要不重復(fù)的隨機(jī)數(shù),如何實(shí)現(xiàn)?本文給于解決方法,需要的朋友可以參考下2012-12-12
設(shè)置點(diǎn)擊文本框或圖片彈出日歷控件的實(shí)現(xiàn)代碼
下面小編就為大家?guī)?lái)一篇設(shè)置點(diǎn)擊文本框或圖片彈出日歷控件的實(shí)現(xiàn)代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧2016-05-05
基于javascript滾動(dòng)圖片具體實(shí)現(xiàn)
這篇文章主要介紹了javascript滾動(dòng)圖片具體實(shí)現(xiàn),有需要的朋友可以參考一下2013-11-11

