MST
星途 面试题库

面试题:Vue中如何实现图片的懒加载

在Vue项目里,描述实现图片懒加载的基本步骤,并且说明使用Vue的指令和生命周期钩子函数在其中如何配合完成懒加载功能。
28.4万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

实现图片懒加载基本步骤

  1. 设置占位符:在模板中,对于需要懒加载的图片,先设置一个占位符(例如一个小的加载图标或者空白图片),初始 src 可以为空或设置为占位图路径。
  2. 获取图片位置信息:获取图片在页面中的位置信息,包括距离页面顶部的距离等,这通常需要在页面滚动过程中动态获取。可以使用 Element.getBoundingClientRect() 方法获取元素相对于视口的位置。
  3. 监听滚动事件:监听页面滚动事件,在滚动过程中,不断检查图片是否进入视口。当图片即将进入或者已经进入视口时,开始加载图片。
  4. 加载图片:当满足加载条件(图片进入视口)时,将真实的图片 src 赋值给图片元素,触发图片加载。

Vue指令与生命周期钩子函数配合实现懒加载

  1. 创建自定义指令
    • 在Vue中可以通过 Vue.directive 创建自定义指令,例如 v - lazyload
    • 在指令的 bind 钩子函数中,可以初始化一些数据,比如保存真实的 src(因为初始 src 可能是占位图),并绑定滚动事件监听。
    Vue.directive('lazyload', {
      bind(el, binding) {
        el._realSrc = binding.value;
        window.addEventListener('scroll', this.handleScroll.bind(this, el));
      },
      unbind(el) {
        window.removeEventListener('scroll', this.handleScroll.bind(this, el));
      },
      handleScroll(el) {
        const rect = el.getBoundingClientRect();
        if (rect.top <= window.innerHeight && rect.bottom >= 0) {
          el.src = el._realSrc;
          window.removeEventListener('scroll', this.handleScroll.bind(this, el));
        }
      }
    });
    
  2. 生命周期钩子函数配合
    • 在组件的 mounted 生命周期钩子函数中,可以触发一次手动检查,确保在组件挂载后,如果图片已经在视口内,立即加载图片。
    export default {
      mounted() {
        this.$nextTick(() => {
          const lazyImages = document.querySelectorAll('[v - lazyload]');
          lazyImages.forEach((img) => {
            const rect = img.getBoundingClientRect();
            if (rect.top <= window.innerHeight && rect.bottom >= 0) {
              img.src = img._realSrc;
            }
          });
        });
      }
    };
    
    • 在组件的 beforeDestroy 生命周期钩子函数中,如果有自定义指令添加的事件监听等,需要进行清理,防止内存泄漏。例如在上述自定义指令中,在 unbind 里已经移除了滚动事件监听,但在组件层面也可以再次确认清理操作。
    export default {
      beforeDestroy() {
        // 如果有额外需要清理的与懒加载相关的操作,在这里进行
      }
    };
    

在模板中使用自定义指令:

<template>
  <img v - lazyload="imageSrc" alt="懒加载图片">
</template>

<script>
export default {
  data() {
    return {
      imageSrc: '真实图片路径'
    };
  }
};
</script>