Intersection?Observer交叉觀察器示例解析
前言
作為一個(gè)前端搬磚仔,偶爾會(huì)遇到關(guān)于視窗的問題...
其中就經(jīng)常會(huì)遇到一些數(shù)據(jù)上報(bào)問題,比如某某組件是否被用戶看到了,如果看到就要上報(bào)數(shù)據(jù),讓產(chǎn)品同學(xué)方便進(jìn)行數(shù)據(jù)分析。
分析這個(gè)場景可以發(fā)現(xiàn),必須要用戶看到了我才能上報(bào),怎么判斷用戶是否看到了這個(gè)組件呢?
傳統(tǒng)的方法是操作dom,通過這些數(shù)據(jù)或方法(offsetTop、scrollTop,getBoundingClientRect)來進(jìn)行比較。
頻繁的對DOM狀態(tài)的計(jì)算,會(huì)造成不小的性能損耗,導(dǎo)致頁面卡頓。
接下來介紹一種我最近比較常用的新方式:Intersection Observer(交叉觀察器)
Intersection Observer 翻譯過來即交叉觀察器
主要是用于監(jiān)聽目標(biāo)元素與指定的元素視窗是否發(fā)生交叉
一句話總結(jié):Intersection Observer API 提供了一種異步檢測目標(biāo)元素與祖先元素或 viewport 相交情況變化的方法。 – MDN
使用
一、利用IntersectionObserver構(gòu)造函數(shù)創(chuàng)建一個(gè)觀察器實(shí)例
<template> <div class="home"></div> </template> <script> export default { name: "HomeView", mounted() { // 可見性發(fā)生變化后的回調(diào) function callback() { console.log("觸發(fā)了"); } // 交叉觀察器配置項(xiàng) let options = {}; // 生成交叉觀察器 const observer = new IntersectionObserver(callback); }, }; </script>
(callback是當(dāng)元素可見比例超過指定閾值后會(huì)調(diào)用的一個(gè)回調(diào)函數(shù),options是一個(gè)可以用來配置 observer 實(shí)例的對象。)
輸出一下IntersectionObserver構(gòu)造函數(shù)返回的實(shí)例
實(shí)例屬性:
root:root 屬性用來獲取當(dāng)前 intersectionObserver 實(shí)例的根元素,用于判斷元素是否可見區(qū)域。
(注:這個(gè)既可以是 target 元素祖先元素也可以是指定 null 則使用瀏覽器視口 做為容器 (root)。)
rootMargin:一個(gè)類似于margin的字符串參數(shù),就可以使用 root margin 來調(diào)整根矩形大小。
(注:由于使用Intersection Observer的過程中所有區(qū)域均被當(dāng)做一個(gè)矩形看待,因此當(dāng)我們需要調(diào)整元素邊界的矩形時(shí),用 root margin 來調(diào)整大小。)
threshold:閾值,可以傳一個(gè)0 ~ 1的number,也可以傳個(gè)0 ~ 1范圍的number數(shù)組。
(注:如果傳一個(gè)0 ~ 1的number,如0.5則說明,目標(biāo)元素和root相交超過50%時(shí),即二者重合超過目標(biāo)元素的50%時(shí),觸發(fā)回調(diào),如果是一個(gè)數(shù)組[0.1, 0.2, 0.5]則分別在10% 20% 50%處觸發(fā)回調(diào))
二、觀察器實(shí)例監(jiān)聽元素相交
<template> <div class="home"> <div id="target" class="target-item"></div> </div> </template> <script> export default { name: "HomeView", mounted() { // 可見性發(fā)生變化后的回調(diào) function callback(data) { console.log("觸發(fā)了"); console.log(data); } // 交叉觀察器配置項(xiàng) let options = {}; // 生成交叉觀察器 const observer = new IntersectionObserver(callback); // 獲取目標(biāo)節(jié)點(diǎn) let target = document.getElementById("target"); // 監(jiān)聽目標(biāo)元素 observer.observe(target); }, }; </script> <style scoped> .home { height: 300vh; } .home .target-item { margin-top: 120vh; width: 20px; height: 20px; background: #000; } </style>
可以看到
通過滾動(dòng),可以不停監(jiān)聽到觀察器的回調(diào)。
三、觀察器回調(diào)函數(shù)參數(shù)
看到在觀察器的回調(diào)中是返回了一個(gè)對象的,修改原來的回調(diào)函數(shù),對應(yīng)看看到底返回了啥?
export default { name: "HomeView", mounted() { // 可見性發(fā)生變化后的回調(diào) function callback(data) { console.log("觸發(fā)了"); data.map((item) => { // 目標(biāo)元素的getBoundingClientRect的返回值。 console.log(item.boundingClientRect); // 目標(biāo)元素和根元素交叉區(qū)域的getBoundingClientRect的返回值。 console.log(item.intersectionRatio); // 目標(biāo)元素的可見比例,相當(dāng)于二者重合了多少。 console.log(item.intersectionRect); // 目標(biāo)元素與根元素是否相交 console.log(item.isIntersecting); // 根元素的getBoundingClientRect的返回值 console.log(item.rootBounds); // 目標(biāo)元素,是個(gè)dom console.log(item.target); // 從首次創(chuàng)建觀察者到觸發(fā)指定閾值發(fā)生交叉的時(shí)間 console.log(item.time); }); } // 交叉觀察器配置項(xiàng) let options = { threshold: 0.5, }; // 生成交叉觀察器 const observer = new IntersectionObserver(callback, options); // 獲取目標(biāo)元素 let target = document.getElementById("target"); // 監(jiān)聽目標(biāo)元素 observer.observe(target); }, };
可以看到控制臺(tái)輸出了下述內(nèi)容:
可以看到返回了很多東西
其中就有我們熟悉的元素的getBoundingClientRect屬性。
回調(diào)參數(shù)屬性:
boundingClientRect: 對象,返回了目標(biāo)元素的getBoundingClientRect的返回值。
intersectionRatio:對象,返回了目標(biāo)元素和根元素交叉區(qū)域的getBoundingClientRect的返回值。
intersectionRect: 數(shù)字,目標(biāo)元素的可見比例,相當(dāng)于二者重合了多少。
isIntersecting: 布爾值,目標(biāo)元素與根元素相交是否相交
(如果相交,則返回 true ,若為true則說明至少到達(dá)了一個(gè)閾值,如果為false,說明目標(biāo)元素在閾值范圍內(nèi)不可見)
rootBounds: 對象,返回了根元素的getBoundingClientRect的返回值。
target:對象,目標(biāo)元素,是個(gè)dom
time: 數(shù)字,從首次創(chuàng)建觀察者到觸發(fā)指定閾值發(fā)生交叉的時(shí)間
因此通過觀察器的回調(diào)參數(shù)可以做到精確監(jiān)聽目標(biāo)的,通過這些參數(shù)可以更好的支持如下拉加載技術(shù)上報(bào)等場景,由于該屬性是原生api因此比起頻繁的操作dom會(huì)來的更絲滑。
四、觀察器的實(shí)例方法
通過上文我們已經(jīng)說明了,如何使用交叉觀察器,并介紹了觀察器的實(shí)例屬性及回調(diào)參數(shù)
下面說一下觀察器的實(shí)例方法!
// 生成交叉觀察器 const observer = new IntersectionObserver(callback, options); // 獲取目標(biāo)元素 let target = document.getElementById("target"); // 監(jiān)聽目標(biāo)元素 observer.observe(target);
可以看到監(jiān)聽目標(biāo)元素的時(shí)候用了 observe 方法,這就是觀察器的實(shí)例方法之一—— 監(jiān)聽目標(biāo)元素
觀察器的實(shí)例方法一共有四個(gè)
disconnect:停止對所有的目標(biāo)元素的觀察
observe:監(jiān)聽目標(biāo)元素(可監(jiān)聽多個(gè))
takeRecords:返回一個(gè)IntersectionObserverEntry對象數(shù)組(觀察器回調(diào)參數(shù)就是這個(gè)),里面存放的各個(gè)目標(biāo)元素的相交信息
unobserve:停止對一個(gè)指定目標(biāo)元素的觀察
通過代碼來演示下上述方法:
<template> <div class="home"> <div id="target1" class="target1-item"></div> <div id="target2" @click="unobserve()" class="target2-item"></div> <div style="margintop: 10px" @click="disconnect">disconnect</div> </div> </template> <script> export default { name: "HomeView", data() { return { observer: {}, }; }, mounted() { // 可見性發(fā)生變化后的回調(diào) function callback(data) { console.log(data[0].target.id); } // 生成交叉觀察器 this.observer = new IntersectionObserver(callback); // 獲取目標(biāo)元素1 let target1 = document.getElementById("target1"); // 獲取目標(biāo)元素2 let target2 = document.getElementById("target2"); // 監(jiān)聽目標(biāo)元素1 this.observer.observe(target1); // 監(jiān)聽目標(biāo)元素2 this.observer.observe(target2); }, methods: { unobserve() { let target2 = document.getElementById("target2"); // 停止監(jiān)聽目標(biāo)元素2 this.observer.unobserve(target2) }, disconnect() { // 停止監(jiān)聽所有目標(biāo)元素 this.observer.disconnect(); }, }, }; </script>
代碼效果如下所示:
可以看到一開始是監(jiān)聽元素1和元素2,接著停止元素2的監(jiān)聽,最后停止所有元素的監(jiān)聽
以上就是Intersection Observer(交叉觀察器)的基本使用了。
五、總結(jié)
(1)利用IntersectionObserver構(gòu)造函數(shù)創(chuàng)建一個(gè)觀察器實(shí)例,設(shè)置其回調(diào)和基本參數(shù)
// 可見性發(fā)生變化后的回調(diào) function callback() { } // 生成交叉觀察器 this.observer = new IntersectionObserver(callback);
(2)獲取目標(biāo)元素節(jié)點(diǎn),并監(jiān)聽該元素
// 獲取目標(biāo)元素 let target = document.getElementById("target"); // 監(jiān)聽目標(biāo)元素 this.observer.observe(target);
(3)回調(diào)中處理相關(guān)邏輯
function callback(data) { console.log(data) }
(4)觀察器使用結(jié)束后,取消對元素的監(jiān)聽
// 停止觀察某個(gè)目標(biāo)元素 observer.unobserve(target); // 關(guān)閉監(jiān)視器 observer.disconnect();
聊聊Intersection Observer各大瀏覽器的支持性 截圖自
總的來說,這個(gè)還是適用于很多瀏覽器的。
各位前端朋友,如果以后有遇到下拉加載或數(shù)據(jù)上報(bào)的場景的話不妨使用一下這個(gè)Intersection Observer
確實(shí)是一個(gè)開發(fā)的好工具。
以上就是Intersection Observer交叉觀察器示例解析的詳細(xì)內(nèi)容,更多關(guān)于Intersection Observer交叉觀察器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
可拖動(dòng)窗口,附帶鼠標(biāo)控制漸變透明,開啟關(guān)閉功能
可拖動(dòng)窗口,附帶鼠標(biāo)控制漸變透明,開啟關(guān)閉功能...2006-06-06js默認(rèn)文本框粘貼事件完美實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了js默認(rèn)文本框粘貼事件完美實(shí)現(xiàn)詳解,2023-01-01JS前端使用canvas實(shí)現(xiàn)物體的點(diǎn)選示例
這篇文章主要為大家介紹了JS前端使用canvas實(shí)現(xiàn)物體的點(diǎn)選示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08微信小程序 合法域名校驗(yàn)出錯(cuò)詳解及解決辦法
這篇文章主要介紹了微信小程序 合法域名校驗(yàn)出錯(cuò)詳解及解決辦法的相關(guān)資料,需要的朋友可以參考下2017-03-03實(shí)踐示例理解js強(qiáng)緩存協(xié)商緩存
這篇文章主要為大家以實(shí)踐示例理解js強(qiáng)緩存協(xié)商緩存,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07JS實(shí)現(xiàn)一個(gè)微信錄音功能過程示例詳解
這篇文章主要介紹了JS實(shí)現(xiàn)一個(gè)微信錄音功能過程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02