MST

星途 面试题库

面试题:Vue项目图片懒加载中处理复杂业务场景的策略

在一个Vue电商项目中,商品图片存在不同规格(如缩略图、高清图、全景图),且需要根据用户设备、网络状况以及用户操作(如鼠标悬停、点击放大)来灵活切换加载不同图片。同时,部分图片还需要结合SEO要求进行预加载。请详细说明你会如何设计并实现该图片懒加载机制,包括使用的技术、数据结构、逻辑处理等方面。
30.1万 热度难度
前端开发Vue

知识考点

AI 面试

面试题答案

一键面试

使用技术

  1. Intersection Observer API:用于实现图片的懒加载。它可以异步观察目标元素与其祖先元素或视口的交集变化情况。在Vue项目中,可以通过指令(directive)的方式使用它。
  2. Vue.js:利用Vue的响应式系统、指令以及组件化特性来管理图片的状态和交互。
  3. Lodash:在处理复杂逻辑时,如防抖、节流等场景下可能会用到,以优化性能。

数据结构

  1. 商品数据结构
{
  id: '商品唯一标识',
  name: '商品名称',
  thumbImage: '缩略图地址',
  highDefImage: '高清图地址',
  panoramaImage: '全景图地址',
  seoImages: ['SEO预加载图片地址1', 'SEO预加载图片地址2']
}
  1. 图片状态数据结构
{
  isLoaded: false, // 图片是否已加载
  isHovered: false, // 鼠标是否悬停在图片上
  isClicked: false // 图片是否被点击
}

逻辑处理

  1. 图片懒加载逻辑
    • 创建一个Vue指令,例如v-lazyload
    • 在指令的bind钩子函数中,使用IntersectionObserver观察图片元素。
    • 当图片进入视口时(即IntersectionObserver的回调触发且intersectionRatio > 0),根据当前图片状态(是否悬停、是否点击等)加载相应规格的图片。
Vue.directive('lazyload', {
  bind(el, binding) {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const { isHovered, isClicked } = binding.value;
          let imgUrl;
          if (isClicked) {
            imgUrl = binding.value.highDefImage;
          } else if (isHovered) {
            imgUrl = binding.value.highDefImage;
          } else {
            imgUrl = binding.value.thumbImage;
          }
          el.src = imgUrl;
          observer.unobserve(el);
        }
      });
    });
    observer.observe(el);
  }
});
  1. 根据用户操作切换图片逻辑
    • 在图片组件中,绑定mouseentermouseleave事件,分别用于设置isHoveredtruefalse
    • 绑定click事件,设置isClickedtrue。根据这些状态的变化,重新触发图片加载逻辑(可以通过重新设置v - lazyload指令的值来实现)。
<template>
  <img v - lazyload="imageData" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" @click="handleClick" />
</template>
<script>
export default {
  data() {
    return {
      imageData: {
        isLoaded: false,
        isHovered: false,
        isClicked: false,
        thumbImage: '...',
        highDefImage: '...',
        panoramaImage: '...',
        seoImages: ['...']
      }
    };
  },
  methods: {
    handleMouseEnter() {
      this.imageData.isHovered = true;
    },
    handleMouseLeave() {
      this.imageData.isHovered = false;
    },
    handleClick() {
      this.imageData.isClicked = true;
    }
  }
};
</script>
  1. SEO图片预加载逻辑
    • 在组件的created钩子函数中,遍历seoImages数组,创建Image对象并设置其src属性,实现预加载。
export default {
  data() {
    return {
      imageData: {
        // 图片数据结构
        seoImages: ['...']
      }
    };
  },
  created() {
    this.imageData.seoImages.forEach(url => {
      const img = new Image();
      img.src = url;
    });
  }
};