摘要:此外,跟蹤尚未延遲加載的元素數(shù)量,以及取消綁定滾動事件處理程序的繁瑣工作將由開發(fā)者來完成。圖像延遲加載列表圖順序加載的組件已經(jīng)開源啦有興趣的同學可以查看使用起來非常簡單
圖片延時加載十分重要,尤其是對于移動端用戶。
從理論上來看,圖像延遲加載機制十分簡單,但實際上卻有很多需要注意的細節(jié)。 此外,有多個不同的用例均受益于延遲加載。 首先,我們來了解一下在 HTML 中延遲加載內(nèi)聯(lián)圖像。
延遲加載是一種在加載頁面時,延遲加載非關(guān)鍵資源的方法, 而這些非關(guān)鍵資源則在需要時才進行加載。 就圖像而言,“非關(guān)鍵”通常是指“屏幕外”。
最近在做一個移動端漫畫應(yīng)用(id.mangaya.mobi),涉及的圖片比較多,如果圖片不做額外處理,會對用戶不太友好,而且lighthouse評分也會因此降低。
場景
主要有兩種場景。
有興趣的同學可以查看react-progressive-lazy-image,使用起來非常簡單!
Senario 1: 圖片延時到在窗口viewport內(nèi)才開始加載。
Senario 2: 用戶觀看漫畫,需要漫畫一張張的順序加載。
原理
圖片懶加載技術(shù)主要通過監(jiān)聽圖片資源容器是否出現(xiàn)在視口區(qū)域內(nèi),來決定圖片資源是否被加載。
那么實現(xiàn)圖片懶加載技術(shù)的核心就是如何判斷元素處于視口區(qū)域之內(nèi)。
實踐那么如何實現(xiàn)呢?
返回的值是一個DOMRect對象,它是getClientRects()元素返回的矩形的并集,即與元素關(guān)聯(lián)的CSS邊框。其結(jié)果是,其包含整個元件,具有只讀的最小矩形left,top,right,bottom,x,y,width,和height性質(zhì)描述在像素整體邊界框。除視口左上角width和height相對于視口左上角的屬性。
下面代碼可以判斷元素是否在窗口內(nèi)
//https://gomakethings.com/how-to-test-if-an-element-is-in-the-viewport-with-vanilla-javascript/
export const elementIsInsideViewport = el => {
const bounding = el.getBoundingClientRect();
return (
bounding.top >= 0 &&
bounding.left >= 0 &&
bounding.bottom <=
(window.innerHeight || document.documentElement.clientHeight) &&
bounding.right <=
(window.innerWidth || document.documentElement.clientWidth)
);
};
可以結(jié)合window.onScroll以及window.onResize事件以及throttle來實現(xiàn)對img元素的判斷。
document.addEventListener("DOMContentLoaded", function() {
let lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
let active = false;
const lazyLoad = function() {
if (active === false) {
active = true;
setTimeout(function() {
lazyImages.forEach(function(lazyImage) {
if ((lazyImage.getBoundingClientRect().top <= window.innerHeight && lazyImage.getBoundingClientRect().bottom >= 0) && getComputedStyle(lazyImage).display !== "none") {
lazyImage.src = lazyImage.dataset.src;
lazyImage.srcset = lazyImage.dataset.srcset;
lazyImage.classList.remove("lazy");
lazyImages = lazyImages.filter(function(image) {
return image !== lazyImage;
});
if (lazyImages.length === 0) {
document.removeEventListener("scroll", lazyLoad);
window.removeEventListener("resize", lazyLoad);
window.removeEventListener("orientationchange", lazyLoad);
}
}
});
active = false;
}, 200);
}
};
document.addEventListener("scroll", lazyLoad);
window.addEventListener("resize", lazyLoad);
window.addEventListener("orientationchange", lazyLoad);
});
此代碼在 scroll 事件處理程序中使用 getBoundingClientRect 來檢查是否有任何 img.lazy 元素處于視口中。 使用 setTimeout 調(diào)用來延遲處理,active 變量則包含處理狀態(tài),用于限制函數(shù)調(diào)用。 延遲加載圖像時,這些元素隨即從元素數(shù)組中移除。 當元素數(shù)組的 length 達到 0 時,滾動事件處理程序代碼隨即移除。
雖然此代碼幾乎可在任何瀏覽器中正常運行,但卻存在潛在的性能問題,即重復(fù)的 setTimeout 調(diào)用可能純屬浪費,即使其中的代碼受限制,它們?nèi)詴\行。 在此示例中,當文檔滾動或窗口調(diào)整大小時,不管視口中是否有圖像,每 200 毫秒都會運行一次檢查。 此外,跟蹤尚未延遲加載的元素數(shù)量,以及取消綁定滾動事件處理程序的繁瑣工作將由開發(fā)者來完成。
最佳實踐 使用 Intersection Observer此方法非常簡單,只需要為元素生成一個IntersectionObserver,并且監(jiān)聽該元素,然后在監(jiān)聽的回調(diào)判斷元素的intersectionRatio比率即可達到所需。這是核心代碼.
componentDidMount() {
const { src, needLazyUtilInViewPort, canLoadRightNow } = this.props;
if (needLazyUtilInViewPort) {
//https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
try {
const node = ReactDOM.findDOMNode(this);
this.observer = new IntersectionObserver(this.insideViewportCb);
this.observer.observe(node);
} catch (err) {
console.log("err in finding node", err);
}
} else {
if (canLoadRightNow) {
this.loadImage(src);
}
}
}
insideViewportCb(entries) {
entries.forEach(element => {
//在viewport里面
if (element.intersectionRatio >0) {
this.loadImage(this.props.src);
}
});
}
不過,Intersection Observer 的缺點是雖然在瀏覽器之間獲得良好的支持,但并非所有瀏覽器皆提供支持。 對于不支持 Intersection Observer 的瀏覽器,您可以使用 polyfill,或者如以上代碼所述,檢測 Intersection Observer 是否可用,并在其不可用時回退到兼容性更好的舊方法。
至于列表圖順序加載的話,只需要在每個圖片回調(diào)通知父組件可以加載下一張就可以了。 總的來說getBoundingClientRect和Intersection Observer都可以實現(xiàn)圖片懶加載,但是getBoundingClientRect如果在當前頁面使用到其他onScroll事件,會出現(xiàn)卡頓等問題,不能非常順暢的滑動,而Intersection Observer使用起來非常簡單流暢。
圖像延遲加載 && 列表圖順序加載的組件已經(jīng)開源啦~!
有興趣的同學可以查看react-progressive-lazy-image,使用起來非常簡單!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/7376.html
摘要:標簽加載順序如果要談標簽加載順序問題,首先要談的就是標簽的位置,因為標簽的位置對于加載順序來說有著很重要的影響。例如標簽在以上代碼中,可能由于下載時間比較長,由于兩個標簽都是異步執(zhí)行,互不干擾,因此可能就會先于執(zhí)行。 談?wù)? 標簽加載順序的問題 這篇文章比較長,如果你耐心讀完了,我會感謝你愿意在這篇文章上花費時間,也希望你有收獲。 其實說起,幾乎搞前端的都知道他的作用:引入 JavaS...
摘要:并減少對樣式的請求。缺點暴露了模塊成員,外部可以修改模塊內(nèi)部狀態(tài)。所有依賴這個模塊的語句,都定義在一個回調(diào)函數(shù)中,等到加載完成之后,這個回調(diào)函數(shù)才會運行。 HTML&&CSS基礎(chǔ)知識點整理 一、WEB標準:一系列標準的集合 1. 結(jié)構(gòu)(Structure):html 語言:XHTML[可擴展超文本標識語言]和XML[可擴展標記語言] 2. 表現(xiàn)(Preasentation):css...
摘要:并減少對樣式的請求。缺點暴露了模塊成員,外部可以修改模塊內(nèi)部狀態(tài)。所有依賴這個模塊的語句,都定義在一個回調(diào)函數(shù)中,等到加載完成之后,這個回調(diào)函數(shù)才會運行。 HTML&&CSS基礎(chǔ)知識點整理 一、WEB標準:一系列標準的集合 1. 結(jié)構(gòu)(Structure):html 語言:XHTML[可擴展超文本標識語言]和XML[可擴展標記語言] 2. 表現(xiàn)(Preasentation):css...
小編寫這篇文章的一個主要目的,主要是給大家就相關(guān)的具體內(nèi)容做出一些詳細解答,比如了解使用python的相關(guān)知識,主要是涉及到python Opencv的一些相關(guān)知識,比如使用python Opencv實現(xiàn)停車位識別,就具體的內(nèi)容,下面給大家詳細解答下。 1.怎么去實現(xiàn) (1)第一是需要用到一個處理畫框的程序,將圖片中的有車和無車的停車位給畫出來,并且保存坐標(如果畫錯了,將鼠標移至要刪除的...
閱讀 1438·2023-04-25 16:31
閱讀 2040·2021-11-24 10:33
閱讀 2744·2021-09-23 11:33
閱讀 2528·2021-09-23 11:31
閱讀 2900·2021-09-08 09:45
閱讀 2336·2021-09-06 15:02
閱讀 2647·2019-08-30 14:21
閱讀 2313·2019-08-30 12:56