图片懒加载

记录一次笔试题

实现一个图片懒加载事件

  1. 使用节流函数,时延1s
  2. 加载完全部图片时销毁监听事件事件

首先我们先实现一个基础的图片懒加载方法

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Lazy Loading with Throttled Scroll</title>
    <style>
        img {
            display: block;
            width: 100%;
            height: 300px;
            margin-bottom: 20px;
        }
    </style>
</head>

<body>
    <img src="https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B"
        alt="">
    <div id="app">
        <img :id="image.id" v-for="image in images" :data-src="image.src" :key="image.id" :alt="image.alt" />
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    images: [
                        { id: 1, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 2, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 3, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 4, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 5, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 6, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 7, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 8, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 9, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 10, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 11, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 12, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                    ]
                };
            },
            mounted() {
                // 监听滚动事件,并使用loadImages函数作为回调函数
                window.addEventListener('scroll', () => {
                    this.loadImages();
                });
                // 初始化加载可见的图片
                this.$nextTick(() => {
                    this.loadImages();
                })
            },
            methods: {
                // 加载图片
                loadImages() {
                    const windowHeight = window.innerHeight;
                    const windowWidth = window.innerWidth;
                
                    for (let i = 0; i < this.images.length; i++) {
                        const image = this.images[i];
                        const imgElement = this.$el.querySelector(`img[id="${image.id}"]`);
                        const imgRect = imgElement.getBoundingClientRect();

                        if (imgRect.top < windowHeight && imgRect.left < windowWidth) {
                            // 图片进入视口,加载真实图片源
                            imgElement.src = image.src
                        }
                    }
                }
            },
        });
    </script>
</body>
</html>

第二步,增加节流函数

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Lazy Loading with Throttled Scroll</title>
    <style>
        img {
            display: block;
            width: 100%;
            height: 300px;
            margin-bottom: 20px;
        }
    </style>
</head>

<body>
    <img src="https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B"
        alt="">
    <div id="app">
        <img :id="image.id" v-for="image in images" :data-src="image.src" :key="image.id" :alt="image.alt" />
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    images: [
                        { id: 1, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 2, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 3, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 4, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 5, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 6, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 7, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 8, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 9, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 10, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 11, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 12, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                    ],
                    throttledLoadImages: null,
                };
            },
            mounted() {
                this.throttledLoadImages = this.throttle(this.loadImages, 1000);
                // 监听滚动事件,并使用节流的loadImages函数作为回调函数
                window.addEventListener('scroll', () => {
                    this.throttledLoadImages();
                });
                // 初始化加载可见的图片
                this.$nextTick(() => {
                    this.loadImages();
                })
            },
            methods: {
                // 加载图片
                loadImages() {
                    const windowHeight = window.innerHeight;
                    const windowWidth = window.innerWidth;
                
                    for (let i = 0; i < this.images.length; i++) {
                        const image = this.images[i];
                        const imgElement = this.$el.querySelector(`img[id="${image.id}"]`);
                        const imgRect = imgElement.getBoundingClientRect();

                        if (imgRect.top < windowHeight && imgRect.left < windowWidth) {
                            // 图片进入视口,加载真实图片源
                            imgElement.src = image.src
                        }
                    }
                },
                // 创建节流函数
                throttle(func, delay) {
                    let startTime = 0
                    return function(...args){
                        const nowTime = new Date().getTime()
                        const waitTime = delay - (nowTime - startTime)
                        if(waitTime <= 0){
                            func.apply(this, args)
                            startTime = nowTime
                        }
                    }
                }
            },
        });
    </script>
</body>
</html>

第三步,添加标志位,表示是否所有图片都已加载完成

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Lazy Loading with Throttled Scroll</title>
    <style>
        img {
            display: block;
            width: 100%;
            height: 300px;
            margin-bottom: 20px;
        }
    </style>
</head>

<body>
    <img src="https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B"
        alt="">
    <div id="app">
        <img :id="image.id" v-for="image in images" :data-src="image.src" :key="image.id" :alt="image.alt" />
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    images: [
                        { id: 1, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 2, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 3, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 4, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 5, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 6, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 7, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 8, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 9, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 10, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 11, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                        { id: 12, src: 'https://uploadfiles.nowcoder.com/images/20240315/677424810_1710464757879/FECD76F09C4EFFA7102ECDBC1795FB3B', alt: '' },
                    ],
                    throttledLoadImages: null,
                };
            },
            mounted() {
                // 创建节流的loadImages函数
                this.throttledLoadImages = this.throttle(this.loadImages, 1000);
                // 监听滚动事件,并使用节流的loadImages函数作为回调函数
                window.addEventListener('scroll', () => {
                    this.throttledLoadImages();
                });
                // 初始化加载可见的图片
                this.$nextTick(() => {
                    this.loadImages();
                })
            },
            beforeDestroy() {
                // 组件销毁前移除滚动事件监听器
                // window.removeEventListener('scroll', this.throttledLoadImages);
            },
            methods: {
                // 加载图片
                loadImages() {
                    const windowHeight = window.innerHeight;
                    const windowWidth = window.innerWidth;
                    let allImagesLoaded = true; // 添加标志位,表示是否所有图片都已加载完成

                    for (let i = 0; i < this.images.length; i++) {
                        const image = this.images[i];
                        const imgElement = this.$el.querySelector(`img[id="${image.id}"]`);
                        const imgRect = imgElement.getBoundingClientRect();

                        if (imgRect.top < windowHeight && imgRect.left < windowWidth && !this.imageLoaded(image)) {
                            // 图片进入视口,加载真实图片源
                            image.loaded = true;
                            imgElement.src = image.src
                        }

                        if (!this.imageLoaded(image)) {
                            allImagesLoaded = false; // 如果存在未加载完成的图片,则将标志位置为false
                        }
                    }

                    if (allImagesLoaded) {
                        // 如果所有图片都已加载完成,则移除滚动事件监听器
                        console.log('销毁事件')
                        window.removeEventListener('scroll', this.throttledLoadImages);
                    }
                },
                // 检查图片是否已加载
                imageLoaded(image) {
                    return image.loaded;
                },
                // 创建节流函数
                throttle(func, delay) {
                    let startTime = 0
                    return function (...args) {
                        const nowTime = new Date().getTime();
                        const waitTime = delay - (nowTime - startTime); // 距离上次执行函数的时间间隔

                        if (waitTime <= 0) {
                            func.apply(this, args)
                            console.log("执行")
                            startTime = nowTime
                        }
                    };
                },
            },
        });
    </script>
</body>

</html>

全部评论

相关推荐

6 4 评论
分享
牛客网
牛客企业服务