IntersectionObserve初试
IntersectionObserve這個API,可能知道的人并不多(我也是最近才知道...),這個API可以很方便的監聽元素是否進入了可視區域。
<style> * {margin: 0;padding: 0; }.test {width: 200px;height: 1000px;background: orange; }.box {width: 150px;height: 150px;margin: 50px;background: red; } </style> <div class="test">test</div> <div class="box">box</div>上圖代碼中,.box元素目前并不在可視區域(viewport)內,如何監聽它進入可視區域內?
傳統做法是:監聽scroll事件,實時計算.box距離viewport的top值:
const box = document.querySelector('.box'); const viewHeight = document.documentElement.clientHeight;window.addEventListener('scroll', () => {const top = box.getBoundingClientRect().top;if (top < viewHeight) {console.log('進入可視區域');} });然而scroll事件會頻繁觸發,因此我們還需要手動節流。
使用IntersectionObserve就非常方便了:
const box = document.querySelector('.box'); const intersectionObserver = new IntersectionObserver((entries) => {entries.forEach((item) => {if (item.isIntersecting) {console.log('進入可視區域');}}) }); intersectionObserver.observe(box);IntersectionObserver API是異步的,不隨著目標元素的滾動同步觸發,所以不會有性能問題。
IntersectionObserver構造函數
const io = new IntersectionObserver((entries) => {console.log(entries); });io.observe(dom);調用IntersectionObserver時,需要給它傳一個回調函數。當監聽的dom元素進入可視區域或者從可視區域離開時,回調函數就會被調用。
注意: 第一次調用new IntersectionObserver時,callback函數會先調用一次,即使元素未進入可視區域。
構造函數的返回值是一個觀察器實例。實例的observe方法可以指定觀察哪個 DOM 節點。
// 開始觀察 io.observe(document.getElementById('example'));// 停止觀察 io.unobserve(element);// 關閉觀察器 io.disconnect();IntersectionObserverEntry對象
callback函數被調用時,會傳給它一個數組,這個數組里的每個對象就是當前進入可視區域或者離開可視區域的對象(IntersectionObserverEntry對象)
這個對象有很多屬性,其中最常用的屬性是:
- target: 被觀察的目標元素,是一個 DOM 節點對象
- isIntersecting: 是否進入可視區域
- intersectionRatio: 相交區域和目標元素的比例值,進入可視區域,值大于0,否則等于0
options
調用IntersectionObserver時,除了傳一個回調函數,還可以傳入一個option對象,配置如下屬性:
- threshold: 決定了什么時候觸發回調函數。它是一個數組,每個成員都是一個門檻值,默認為[0],即交叉比例(intersectionRatio)達到0時觸發回調函數。用戶可以自定義這個數組。比如,[0, 0.25, 0.5, 0.75, 1]就表示當目標元素 0%、25%、50%、75%、100% 可見時,會觸發回調函數。
- root: 用于觀察的根元素,默認是瀏覽器的視口,也可以指定具體元素,指定元素的時候用于觀察的元素必須是指定元素的子元素
- rootMargin: 用來擴大或者縮小視窗的的大小,使用css的定義方法,10px 10px 30px 20px表示top、right、bottom 和 left的值
懶加載
圖片懶加載的原理就是:給img標簽一個自定義屬性,用來記錄真正的圖片地址。默認img標簽只加載一個占位符。當圖片進入可視區域時,再把img的src屬性更換成真正的圖片地址。
<div><img src="/empty.jpg" data-src="https://segmentfault.com/img/1.jpg" /><img src="/empty.jpg" data-src="https://segmentfault.com/img/2.jpg" /> </div> const intersectionObserver = new IntersectionObserver((entries) => {entries.forEach((item) => {if (item.isIntersecting) {item.target.src = item.target.dataset.src;// 替換成功后,停止觀察該domintersectionObserver.unobserve(item.target);}})}, {rootMargin: "150px 0px" // 提前150px進入可視區域時就加載圖片,提高用戶體驗});const imgs = document.querySelectorAll('[data-src]'); imgs.forEach((item) => {intersectionObserver.observe(item) });打點上報
前端頁面經常有上報數據的需求,比如統計頁面上的某些元素是否被用戶查看,點擊。這時,我們就可以封裝一個Log組件,用于當元素進入可視區域時,就上報數據。
以React為例,我們希望:被Log組件包裹的元素,進入可視區域后,就向后臺發送{ appid: 1234, type: 'news'}數據
兼容性
safari并不支持該API,因此為了兼容主流瀏覽器,我們需要引入polyfill
intersection-observer
總結
以上是生活随笔為你收集整理的IntersectionObserve初试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: innodb Cardinality学习
- 下一篇: 你与弄懂promise之间可能只差这篇文