首頁 > 軟體

JavaScript懶載入與預載入原理與實現詳解

2022-09-20 22:01:31

1、懶載入

1.1、什麼是懶載入

懶載入也可以叫做延遲載入,當存取一個頁面的時候,先把img元素伙食其他元素的背景圖片路徑替換成一張大小為1*1px圖片的路徑(這樣只需要請求一次,俗稱佔點陣圖);

只有當圖片出現在瀏覽器的可視區域內時,才這隻圖片真正的路徑,讓圖片顯示出來,這就是圖片懶載入。

1.2、為什麼要使用懶載入

當頁面很多,內容很豐富的時候,頁面很長,圖片較多,比如各個商城頁面,要是頁面載入就一次性載入完畢,就需要等很長的時間

1.3、懶載入的優點

按需載入,頁面載入速度快,節約流量,使用者體驗感好,減少伺服器壓力

1.4、懶載入的原理

頁面中的img元素,如果沒有src屬性, 瀏覽器就不會發出請求去下載圖片,只有通過javascript設定了圖片路徑,瀏覽器才會傳送請求。

懶載入的原理就是先在頁面中把所有的圖片統一使用一張佔點陣圖進行佔位,把真正的路徑存在元素的"data-url"(這個名字起個自己認識好記的就行)屬性裡,要用的時候就取出來放在src裡面

1.5、懶載入的實現步驟

  1. 首先,不要將圖片地址放到src屬性中,而是放到其它屬性(data-origina)中。
  2. 頁面載入完成後,判斷圖片是否在使用者的視野內,如果在,則將data-original屬性中的值取出存放到src屬性中

1.6、懶載入的實現方式

<ul>
    <li><img src="../img/loading.gif" alt="" data-src="../img/1.jpg"></li>
    <li><img src="../img/loading.gif" alt="" data-src="../img/2.jpg"></li>
    <li><img src="../img/loading.gif" alt="" data-src="../img/3.jpg"></li>
    <li><img src="../img/loading.gif" alt="" data-src="../img/4.jpg"></li>
    <li><img src="../img/loading.gif" alt="" data-src="../img/5.jpg"></li>
    <li><img src="../img/loading.gif" alt="" data-src="../img/6.jpg"></li>
    <li><img src="../img/loading.gif" alt="" data-src="../img/7.jpg"></li>
    <li><img src="../img/loading.gif" alt="" data-src="../img/8.jpg"></li>
</ul>

方式1:通過 元素距離頂部的高度 - 卷軸捲動的高度 < =視窗視覺化區域高度 進行判斷;

    /*元素距離頂部的高度-頁面被捲去的高度<=瀏覽器可視區域的高度
    如果條件滿足,就可以替換圖片的src屬性
    */
   //獲取圖片
    const imgArr = document.querySelectorAll("img");
    //初始化執行
    lazyLoad();
    //監聽使用者是否捲動卷軸,但是這高觸發事件,所以需要結合節流優化
    window.addEventListener("scroll", throttle(lazyLoad, 2000));
    function lazyLoad() {
        imgArr.forEach(item => {
            //1、獲取圖片距離頂部的高度
            const imgOffsetTop = item.offsetTop;
            //2、獲取瀏覽器的可視區域的高度
            const wHeight = window.innerHeight;
            //3、獲取頁面被捲去的高度
            const scrollHeight = document.documentElement.scrollTop;
            //判斷圖片是否將要出現
            if (imgOffsetTop - scrollHeight <= wHeight) {
                item.src = item.getAttribute("data-src");
            }
        })
    }
    //節流
    function throttle(fun, time = 250) {
        let lastTime = 0;//最後一次執行的時間
        return function (...args) {
            const now = new Date().getTime();//獲取當前的時間
            if (now - lastTime >= time) {
                fun();
                lastTime = now;
            }
        }
    }

方式2:getBoundingClientRect()

  • 獲取元素位置, 這個方法沒有引數
  • 用於獲得頁面中某個元素的左,上, 右和下分別相對瀏覽器視窗的位置。
  • 是DOM元素到瀏覽器可視範圍的距離(不包含檔案捲起的部分)
  • 該函數返回一個0bject物件, 該物件有6個屬性: top, lef, right, bottom , width, height;

    const imgArr = document.querySelectorAll("img");
    //初始化執行
    lazyLoad()
    //監聽使用者是否捲動卷軸,但是這高觸發事件,所以需要結合節流優化
   //監聽使用者是否捲動卷軸,但是這高觸發事件,所以需要結合節流優化
    window.addEventListener("scroll", throttle(lazyLoad, 2000));
    function lazyLoad() {
        imgArr.forEach(item => {
            //獲取圖片和頂部的高度
            const imgTop = item.getBoundingClientRect().top;
            //獲取瀏覽器視覺化區域高度
            const wHeight = window.innerHeight;
            //圖片和頂部的高度小於瀏覽器視窗視覺化區域的高度
            if (imgTop <= wHeight) {
                //getAttribute獲取自定義屬性
                // item.src = item.getAttribute("data-src");
                //也可以使用dataset來獲取自定義屬性的值
                item.src = item.dataset.src;
            }
        })
    }
    //節流
    function throttle(fun, time = 250) {
        let lastTime = 0;//最後一次執行的時間
        return function (...args) {
            const now = new Date().getTime();//獲取當前的時間
            if (now - lastTime >= time) {
                fun();
                lastTime = now;
            }
        }
    }

方式3:IntersectionObserver(callback)建構函式

callback回撥觸發兩次,看見了觸發,看不見也觸發。

範例有兩個方法:

  • observe給元素新增觀察
  • unobserve取消對元素觀察

    const callback = (res) => {
        //res是一個陣列,所以還需要遍歷
        console.log(res);
        res.forEach(item => {
            //isIntersecting是否在可視區域展示
            if (item.isIntersecting) {
                //獲取圖片的自定義屬性並賦值給src
                item.target.src = item.target.dataset.src;
                //替換為真是src地址後取消對它的觀察
                observe.unobserve(item.target);
            }
        })
    }
    //1、範例化建構函式
    const observe = new IntersectionObserver(callback);
    const imgArr = document.querySelectorAll("img");
    //遍歷所有的圖片,給每個圖片新增觀察
    imgArr.forEach(item => {
        //觀察圖片
        observe.observe(item)
    })

2、預載入

2.1、什麼是預載入

資源預載入是另一個效能優化技術,我們可以使用該技術來預先告知瀏覽器某些資源可能在將來會被使用到。預載入簡單來說就是將所有所需的資源提前請求載入到本地,這樣後面在需要用到時就直接從快取取資源。

2.2、為什麼要使用預載入

在網頁全部載入之前,對一些主要內容進行載入,以提供給使用者更好的體驗,減少等待的時間。否則,如果一個頁面的內容過於龐大,沒有使用預載入技術的頁面就會長時間的展現為一片空白,直到所有內容載入完畢。

2.3、實現預載入的方法

<div>
    <p></p>
    <img src="../img/1.jpg" alt="">
</div>
<script type="text/javascript">
    const imgArr = ["../img/2.jpg", "../img/3.jpg", "../img/4.jpg", "../img/5.jpg", "../img/6.jpg", "../img/7.jpg"]
    const img = document.querySelector("img");
    const p = document.querySelector("p");
    //定義預設的index的值
    let index = 0;
    p.innerHTML = `實現預載入的效果,我是第${index + 1}張圖片`;
    img.addEventListener("click", (e) => {
        if (index < imgArr.length) {
            img.src = imgArr[index];
            index++;
            p.innerHTML = `實現預載入的效果,我是第${index + 1}張圖片`;
            if (index < imgArr.length) {
                //切換圖片後,同時讓瀏覽器提前載入下一張圖片
                preLoad(imgArr[index])
            }
        } else {
            confirm("沒有圖片了")
        }
    }, false)
    //呼叫預載入函數,頁面一開始就載入陣列的第一個元素
    preLoad(imgArr[0])
    //定義預載入函數
    function preLoad(src) {
        //當圖片失去焦點後
        img.addEventListener("load", () => {
            //建立一個新的img標籤
            const imgNew = document.createElement("img");
            //給img標籤新增src屬性為我們傳進來的src
            imgNew.src = src;
        })
    }
</script>

到此這篇關於JavaScript懶載入與預載入原理與實現詳解的文章就介紹到這了,更多相關JS懶載入與預載入內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com