首頁  >  文章  >  web前端  >  懶加載實作的方法有哪些? (三種方法介紹)

懶加載實作的方法有哪些? (三種方法介紹)

不言
不言轉載
2019-01-08 10:26:503936瀏覽

本篇文章帶給大家的內容是關於懶加載實現的方法有哪些? (三種方法介紹),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

優勢

  1. 效能效益:瀏覽器載入圖片、decode、渲染都需要耗費資源,懶載入能節省效能消耗,縮短onload事件時間。

  2. 節約頻寬:這個不需要解釋。

通常,我們在html中展示圖片,會有兩種方式:

  1. #img 標籤

  2. css background-image

#img的懶載入實作

img有兩種方式實作懶載入:

  1. # #事件監聽(scroll、resize、orientationChange)

  2. <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>event</title>
        <style>
            img {
                background: #F1F1FA;
                width: 400px;
                height: 300px;
                display: block;
                margin: 10px auto;
                border: 0;
            }
        </style>
    </head>
    <body>
        <img src="https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300" />
        <img src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
        <img src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" /> -->
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image5.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image6.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image7.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image8.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image9.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image10.jpeg?tr=w-400,h-300" />
        <script>
            document.addEventListener("DOMContentLoaded", function() {
                var lazyloadImages = document.querySelectorAll("img.lazy");    
                var lazyloadThrottleTimeout;
                
                function lazyload () {
                    if(lazyloadThrottleTimeout) {
                        clearTimeout(lazyloadThrottleTimeout);
                    }    
                    
                    lazyloadThrottleTimeout = setTimeout(function() {
                        var scrollTop = window.pageYOffset;
                        lazyloadImages.forEach(function(img) {
                            if(img.offsetTop < (window.innerHeight + scrollTop)) {
                                img.src = img.dataset.src;
                                img.classList.remove(&#39;lazy&#39;);
                            }
                        });
                        if(lazyloadImages.length == 0) {
                            document.removeEventListener("scroll", lazyload);
                            window.removeEventListener("resize", lazyload);
                            window.removeEventListener("orientationChange", lazyload);
                        }
                    }, 20);
                }
                
                document.addEventListener("scroll", lazyload);
                window.addEventListener("resize", lazyload);
                window.addEventListener("orientationChange", lazyload);
            });
        </script>
    </body>
    </html>
  1. Intersection Observer(相容性問題)

  2. <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>observer</title>
        <style>
            img {
                background: #F1F1FA;
                width: 400px;
                height: 300px;
                display: block;
                margin: 10px auto;
                border: 0;
            }
        </style>
    </head>
    <body>
        <img src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
        <img src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" /> -->
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image2.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image3.jpg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image5.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image6.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image7.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image8.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image9.jpeg?tr=w-400,h-300" />
        <img class="lazy" src="https://ik.imagekit.io/demo/img/image10.jpeg?tr=w-400,h-300" />
        <script>
            document.addEventListener("DOMContentLoaded", function() {
                var lazyloadImages = document.querySelectorAll(".lazy");
                var imageObserver = new IntersectionObserver(function(entries, observer) {
                    entries.forEach(function(entry) {
                        if (entry.isIntersecting) {
                            var image = entry.target;
                            image.src = image.dataset.src;
                            image.classList.remove("lazy");
                            imageObserver.unobserve(image);
                        }
                    });
                });
                lazyloadImages.forEach(function(image) {
                    imageObserver.observe(image);
                });
            });
        </script>
    </body>
    </html>
background -image的實作

background-image的實作跟img的原理基本上是一樣的,差別在於在對class的處理上:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>background</title>
    <style>
        body {
            margin: 0;
        }
        .bg {
            height: 200px;
        }
        #bg-image.lazy {
            background-image: none;
            background-color: #F1F1FA;
        }
        #bg-image {
            background-image: url("https://ik.imagekit.io/demo/img/image1.jpeg?tr=w-400,h-300");
            background-size: 100%;
        }
    </style>
</head>
<body>
    <p id="bg-image" class="bg lazy"></p>
    <p id="bg-image" class="bg lazy"></p>
    <p id="bg-image" class="bg lazy"></p>
    <p id="bg-image" class="bg lazy"></p>
    <p id="bg-image" class="bg lazy"></p>
    <p id="bg-image" class="bg lazy"></p>
    <p id="bg-image" class="bg lazy"></p>
    <p id="bg-image" class="bg lazy"></p>
    <script>
        document.addEventListener("DOMContentLoaded", function() {
            var lazyloadImages = document.querySelectorAll(".lazy");
            var imageObserver = new IntersectionObserver(function(entries, observer) {
                entries.forEach(function(entry) {
                    if (entry.isIntersecting) {
                        var image = entry.target;
                        image.classList.remove("lazy");
                        imageObserver.unobserve(image);
                    }
                });
            });
            lazyloadImages.forEach(function(image) {
                imageObserver.observe(image);
            });
        });
    </script>
</body>
</html>
漸進式懶載入

#漸進式懶加載,指的是存在降級處理,通常html形式如下:

<a href="full.jpg" class="progressive replace">
  <img src="tiny.jpg" class="preview" alt="image" />
</a>
這樣的程式碼會有2個好處:

  1. 如果js執行失敗,可以點選預覽

  2. 大小與實際圖一致的佔位數據 URI,避免reflow

最終的程式碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>progressive</title>
    <style>
        a.progressive {
            position: relative;
            display: block;
            overflow: hidden;
            outline: none;
        }
        a.progressive:not(.replace) {
            cursor: default;
        }
        a.progressive img {
            display: block;
            width: 100%;
            max-width: none;
            height: auto;
            border: 0 none;
        }
        a.progressive img.preview {
            filter: blur(2vw);
            transform: scale(1.05);
        }
        a.progressive img.reveal {
            position: absolute;
            left: 0;
            top: 0;
            will-change: transform, opacity;
            animation: reveal 1s ease-out;
        }
        @keyframes reveal {
            0% {transform: scale(1.05); opacity: 0;}
            100% {transform: scale(1); opacity: 1;}
        }
    </style>
</head>
<body>
    <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5.jpg" srcset="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5.jpg 800w, https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5big.jpg 1600w" class="progressive replace">
        <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gNzAK/9sAQwAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7/8AAEQgABQAUAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A5yC3e2S3gM7OEQHdgA57VTuLAPqUoaUk7yM7R2BPSiivS5VN8stjmk2ldGVM3lyshG7bxk0UUV4skk2jdN2P/9k=" class="preview" alt="palm trees" />
    </a>
    <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature2.jpg" class="progressive replace">
        <img src="http://lorempixel.com/20/15/nature/2/" class="preview" alt="sunset" />
    </a>
    <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature3.jpg" class="progressive replace">
        <img src="http://lorempixel.com/20/15/nature/3/" class="preview" alt="tide" />
    </a>
    <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5.jpg" srcset="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5.jpg 800w, https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature5big.jpg 1600w" class="progressive replace">
        <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gNzAK/9sAQwAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7/8AAEQgABQAUAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A5yC3e2S3gM7OEQHdgA57VTuLAPqUoaUk7yM7R2BPSiivS5VN8stjmk2ldGVM3lyshG7bxk0UUV4skk2jdN2P/9k=" class="preview" alt="palm trees" />
    </a>
    <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature2.jpg" class="progressive replace">
        <img src="http://lorempixel.com/20/15/nature/2/" class="preview" alt="sunset" />
    </a>
    <a href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/123941/nature3.jpg" class="progressive replace">
        <img src="http://lorempixel.com/20/15/nature/3/" class="preview" alt="tide" />
    </a>
    <script>
        window.addEventListener('load', function() {
            var pItem = document.getElementsByClassName('progressive replace'), timer;

            window.addEventListener('scroll', scroller, false);
            window.addEventListener('resize', scroller, false);
            inView();

            function scroller(e) {
                timer = timer || setTimeout(function() {
                    timer = null;
                    requestAnimationFrame(inView);
                }, 300);
            }

            function inView() {
                var scrollTop = window.pageYOffset;
                var innerHeight = window.innerHeight;
                var p = 0;
                while (p < pItem.length) {
                    var offsetTop = pItem[p].offsetTop;
                    if (offsetTop < (scrollTop + innerHeight)) {
                        loadFullImage(pItem[p]);
                        pItem[p].classList.remove('replace');
                    }
                    else p++;
                }
            }


            function loadFullImage(item) {
                var img = new Image();
                if (item.dataset) {
                    img.srcset = item.dataset.srcset || '';
                    img.sizes = item.dataset.sizes || '';
                }
                img.src = item.href;
                img.className = 'reveal';
                if (img.complete) addImg();
                else img.onload = addImg;

                function addImg() {
                    item.addEventListener('click', function(e) { e.preventDefault(); }, false);
                    item.appendChild(img).addEventListener('animationend', function(e) {
                        var pImg = item.querySelector('img.preview');
                        if (pImg) {
                            e.target.alt = pImg.alt || '';
                            item.removeChild(pImg);
                            e.target.classList.remove('reveal');
                        }
                    });
                }

            }

        }, false);
    </script>
</body>
</html>
現成函式庫

推薦下面這個函式庫,使用非常簡單:https://www.npmjs.com/package/lozad

以上是懶加載實作的方法有哪些? (三種方法介紹)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除