?xml version="1.0" encoding="UTF-8"?
一灿里、判斷DOM活躍時(shí)長(zhǎng)需監(jiān)聽(tīng)到的情況
1.刪除添加DOM
2.樣式改變
3.單頁(yè)應(yīng)用頁(yè)面跳轉(zhuǎn)
4.頁(yè)面變?yōu)榉腔钴S狀態(tài)
5.頁(yè)面滾動(dòng)DOM是否在停留可視區(qū)內(nèi)
二盹靴、實(shí)現(xiàn)方式
?xml version="1.0" encoding="UTF-8"?
三個(gè)監(jiān)聽(tīng)listener事件&兩個(gè)setTimeout定時(shí)器實(shí)現(xiàn)監(jiān)聽(tīng)DOM活動(dòng)時(shí)長(zhǎng)的功能
domCollectionListener:收集需要監(jiān)聽(tīng)的dom/DOM元素的刪減
Mutation Observer(變動(dòng)觀察器)是監(jiān)視DOM變動(dòng)的接口悬而。當(dāng)DOM對(duì)象樹(shù)【1】發(fā)生任何變動(dòng)時(shí)鉴腻,Mutation Observer會(huì)得到通知。
解析器輸出的樹(shù)是由DOM元素和屬性節(jié)點(diǎn)組成的
要概念上淮逻,它很接近事件爽锥。可以理解為浪默,當(dāng)DOM發(fā)生變動(dòng)會(huì)觸發(fā)Mutation Observer事件牡直。但是缀匕,它與事件有一個(gè)本質(zhì)不同:事件是同步觸發(fā),也就是說(shuō)DOM發(fā)生變動(dòng)立刻會(huì)觸發(fā)相應(yīng)的事件碰逸;Mutation Observer則是異步觸發(fā)乡小,DOM發(fā)生變動(dòng)以后,并不會(huì)馬上觸發(fā)饵史,而是要等到當(dāng)前所有DOM操作都結(jié)束后才觸發(fā)满钟。
Mutation Observer有以下特點(diǎn):
它等待所有腳本任務(wù)完成后,才會(huì)運(yùn)行胳喷,即采用異步方式
它把DOM變動(dòng)記錄封裝成一個(gè)數(shù)組進(jìn)行處理湃番,而不是一條條地個(gè)別處理DOM變動(dòng)。
它即可以觀察發(fā)生在DOM節(jié)點(diǎn)的所有變動(dòng)吭露,也可以觀察某一類變動(dòng) — 自定義
MutationObserver所觀察的DOM變動(dòng)(即上面代碼的option對(duì)象)吠撮,包含以下類型:
childList:子元素的變動(dòng)
attributes:屬性的變動(dòng)
characterData:節(jié)點(diǎn)內(nèi)容或節(jié)點(diǎn)文本的變動(dòng)
subtree:所有下屬節(jié)點(diǎn)(包括子節(jié)點(diǎn)和子節(jié)點(diǎn)的子節(jié)點(diǎn))的變動(dòng)
varobserver =newMutationObserver(callback);
observe.observe(target,{{
????????attributes: true,
????????childList: true,
????????characterData: true,
????????subtree: true,
}?});
解決:需要監(jiān)聽(tīng)DOM元素
initDisplay/inDisplayListener監(jiān)聽(tīng)屬性的變動(dòng)
除了變動(dòng)類型,option對(duì)象還可以設(shè)定以下屬性:
attributeOldValue:值為true讲竿,則表示需要記錄變動(dòng)前的屬性值泥兰。
characterDataOldValue:值為true,則表示需要記錄變動(dòng)前的數(shù)據(jù)值题禀。
attributesFilter:值為一個(gè)數(shù)組鞋诗,表示需要觀察的特定屬性(比如['class', 'str'])。
varobserver =newMutationObserver(callback);
observe.observe(target,{?
?? ?attributeFilter: ['class', 'style'],
?? ?attributeOldValue: true
});
exportconstunDisplay:Object= {
?? ?display:['none'],
?? ?visibility:['collapse','hidden'],
?? ?opacity:[0,'0'],
};
inviewportListener:監(jiān)聽(tīng)DOM元素是否在viewport中
監(jiān)聽(tīng)到scroll事件后迈嘹,調(diào)用目標(biāo)元素(綠色方塊)的getBoundingClientRect()方法削彬,得到它對(duì)應(yīng)于視口左上角的坐標(biāo),再判斷是否在視口之內(nèi)秀仲。這種方法的缺點(diǎn)是融痛,由于scroll事件密集發(fā)生,計(jì)算量很大神僵,容易造成性能問(wèn)題酌心。
IntersectionObserver瀏覽器原生提供的構(gòu)造函數(shù),接受兩個(gè)參數(shù):callback是可見(jiàn)性變化時(shí)的回調(diào)函數(shù)callback一般會(huì)觸發(fā)兩次挑豌。一次是目標(biāo)元素剛剛進(jìn)入視口(開(kāi)始可見(jiàn))安券,另一次是完全離開(kāi)視口(開(kāi)始不可見(jiàn))構(gòu)造函數(shù)的返回值是一個(gè)觀察器實(shí)例。實(shí)例的observe方法可以指定觀察哪個(gè) DOM 節(jié)點(diǎn)
callback函數(shù)的參數(shù)(entries)是一個(gè)數(shù)組氓英,每個(gè)成員都是一個(gè)IntersectionObserverEntry對(duì)象侯勉。舉例來(lái)說(shuō),如果同時(shí)有兩個(gè)被觀察的對(duì)象的可見(jiàn)性發(fā)生變化铝阐,entries數(shù)組就會(huì)有兩個(gè)成員址貌。
var io = new IntersectionObserver(callback, option);
io.observe(document.getElementById('example'));
{
??time: 3893.92,
??rootBounds: ClientRect {
????bottom: 920,
????height: 1024,
????left: 0,
????right: 1024,
????top: 0,
????width: 920
??},
??boundingClientRect: ClientRect {
?????// ...
??},
??intersectionRect: ClientRect {
????// ...
??},
??intersectionRatio: 0.54,
??target: element
}
time:可見(jiàn)性發(fā)生變化的時(shí)間,是一個(gè)高精度時(shí)間戳,單位為毫秒
target:被觀察的目標(biāo)元素练对,是一個(gè) DOM 節(jié)點(diǎn)對(duì)象
rootBounds:根元素的矩形區(qū)域的信息遍蟋,getBoundingClientRect()方法的返回值,如果沒(méi)有根元素(即直接相對(duì)于視口滾動(dòng))螟凭,則返回null
boundingClientRect:目標(biāo)元素的矩形區(qū)域的信息
intersectionRect:目標(biāo)元素與視口(或根元素)的交叉區(qū)域的信息
intersectionRatio:目標(biāo)元素的可見(jiàn)比例虚青,即intersectionRect占boundingClientRect的比例,完全可見(jiàn)時(shí)為1螺男,完全不可見(jiàn)時(shí)小于等于0
注意:
IntersectionObserver API 是異步的棒厘,不隨著目標(biāo)元素的滾動(dòng)同步觸發(fā)。
規(guī)格寫(xiě)明下隧,IntersectionObserver的實(shí)現(xiàn)奢人,應(yīng)該采用requestIdleCallback(),即只有線程空閑下來(lái)淆院,才會(huì)執(zhí)行觀察器何乎。這意味著,這個(gè)觀察器的優(yōu)先級(jí)非常低土辩,只在其他任務(wù)執(zhí)行完宪赶,瀏覽器有了空閑才會(huì)執(zhí)行。
3.監(jiān)聽(tīng)頁(yè)面的可見(jiàn)性
對(duì)history的popstate事件的監(jiān)聽(tīng)可感知到瀏覽器操作導(dǎo)致的路由變化脯燃,如前進(jìn)、后退 對(duì)pushState蒙保、replaceState方法的增強(qiáng)改寫(xiě)來(lái)感知單頁(yè)面應(yīng)用切換路由的操作
第一個(gè)定時(shí)器
設(shè)置最長(zhǎng)的上報(bào)時(shí)間間隔辕棚,每次發(fā)生變動(dòng)時(shí)重新計(jì)時(shí),達(dá)到最大時(shí)間間隔自動(dòng)發(fā)送&重新計(jì)時(shí)
第二個(gè)定時(shí)器
曝光時(shí)長(zhǎng)閾值(單位:秒)邓厕,當(dāng)次時(shí)間內(nèi)沒(méi)有活動(dòng)事件則累計(jì)曝光時(shí)長(zhǎng)逝嚎,進(jìn)入非曝光狀態(tài),默認(rèn)30秒