Bootstrap

图片预加载和懒加载

图片预加载

图片预加载是指在页面展示之前提前加载即将使用到的图片资源,以便当用户需要查看时,能够直接从本地缓存中快速渲染,从而提高页面加载速度和用户体验。

原理

图片预加载通过提前将图片下载到浏览器缓存中,当用户实际需要查看图片时,可以直接从缓存中读取,避免了再次从服务器下载的过程,从而减少了加载时间。

实现方法

  • 使用HTML标签:在HTML中直接插入标签,并设置src属性为要预加载的图片URL,同时可以通过设置style="display:none;"来隐藏图片,使其不影响页面布局。
<!-- 在HTML中直接插入<img>标签,并设置src属性为要预加载的图片URL,同时隐藏图片 -->  
<img src="preload-image.jpg" style="display:none;" alt="Preloaded Image">
  • 使用CSS:通过CSS的background-image属性将图片作为背景图加载,并设置足够大的负偏移量,使其不在页面上显示。
<!-- 在HTML中插入一个用于预加载的元素 -->  
<div class="preload-image"></div>  
  
<!-- 在CSS中设置背景图和足够大的负偏移量 -->  
<style>  
.preload-image {  
  width: 1px; /* 设置为1px,因为只是为了预加载 */  
  height: 1px;  
  background-image: url('preload-image.jpg');  
  background-position: -9999px -9999px; /* 设置足够大的负偏移量 */  
}  
</style>
  • 使用JavaScript:创建一个新的Image对象,设置其src属性为要预加载的图片URL,并监听onload事件以确保图片加载完成。
//在HTML中可能不需要特别的标记,除非想在加载完成后显示图片  
//在JavaScript中创建一个新的Image对象,并设置src属性和onload事件 
<script>  
var preloadImage = new Image();  
preloadImage.src = 'preload-image.jpg';  
preloadImage.onload = function() {  
  // 图片加载完成后的操作,例如:console.log('图片预加载完成!');  
  console.log('图片预加载完成!');  
};  
</script>

图片懒加载

图片懒加载(也称为延迟加载)是指在页面加载完成后,只加载用户当前可见区域或即将进入可见区域的图片资源。当用户滚动页面时,再根据需要加载其他区域的图片。

原理

图片懒加载通过延迟加载非必要资源,减少了初始页面加载时间和网络请求量。它只加载用户当前能够看到或即将看到的图片,对于当前不可见的图片则暂时不加载,从而提高了页面的性能和用户体验。

实现方式

  • 监听滚动事件:通过监听页面的滚动事件,判断哪些图片已经进入了用户的可视区域,然后动态设置这些图片的src属性为真实的图片URL。
<template>  
  <div>  
    <img  
      v-for="image in images"  
      :key="image.id"  
      :data-src="image.src"  
      class="lazy"  
      @load="handleImageLoad"  
      alt="Lazy loaded image"  
    />  
  </div>  
</template>  
  
<script>  
import { onMounted, onUnmounted, ref } from 'vue';  
  
export default {  
  setup() {  
    const images = ref([  
      { id: 1, src: 'real-image-1.jpg' },  
      { id: 2, src: 'real-image-2.jpg' },  
      // 更多图片...  
    ]);  
  
    const handleImageLoad = () => {  
      // 图片加载完成的处理逻辑  
    };  
  
    const isInViewport = (element) => {  
      const rect = element.getBoundingClientRect();  
      return (  
        rect.top >= 0 &&  
        rect.left >= 0 &&  
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&  
        rect.right <= (window.innerWidth || document.documentElement.clientWidth)  
      );  
    };  
  
    const lazyLoad = () => {  
      const imgs = document.querySelectorAll('img.lazy');  
      imgs.forEach((img) => {  
        if (isInViewport(img) && !img.complete) {  
          img.src = img.dataset.src;  
        }  
      });  
    };  
  
    onMounted(() => {  
      window.addEventListener('scroll', lazyLoad);  
      window.addEventListener('resize', lazyLoad);  
      lazyLoad(); // 初始加载  
    });  
  
    onUnmounted(() => {  
      window.removeEventListener('scroll', lazyLoad);  
      window.removeEventListener('resize', lazyLoad);  
    });  
  
    return { images, handleImageLoad };  
  },  
};  
</script>  
  
<style>  
img.lazy {  
  width: 100%;  
  height: auto;  
  opacity: 0;  
  transition: opacity 0.3s;  
}  
img.lazy.loaded {  
  opacity: 1;  
}  
</style>
  • 使用Intersection Observer API:Intersection Observer API提供了一种异步监听目标元素与其祖先元素或顶级文档视窗交叉状态的方法。当目标元素进入可视区域时,可以自动触发加载操作。
<template>  
  <div>  
    <img  
      v-for="image in images"  
      :key="image.id"  
      :data-src="image.src"  
      class="lazy"  
      @load="handleImageLoad"  
      alt="Lazy loaded image"  
      ref="imageRefs"  
    />  
  </div>  
</template>  
  
<script>  
import { onMounted, ref } from 'vue';  
  
export default {  
  setup() {  
    const images = ref([  
      { id: 1, src: 'real-image-1.jpg' },  
      { id: 2, src: 'real-image-2.jpg' },  
      // 更多图片...  
    ]);  
  
    const imageRefs = ref([]);  
  
    const handleImageLoad = () => {  
      // 图片加载完成的处理逻辑  
    };  
  
    const observer = new IntersectionObserver((entries) => {  
      entries.forEach((entry) => {  
        if (entry.isIntersecting) {  
          const img = entry.target;  
          img.src = img.dataset.src;  
          observer.unobserve(img);  
        }  
      });  
    }, {  
      rootMargin: '0px',  
      threshold: 0.1  
    });  
  
    onMounted(() => {  
      imageRefs.value.forEach((img) => {  
        observer.observe(img);  
      });  
    });  
  
    return { images, handleImageLoad, imageRefs };  
  },  
};  
</script>  
  
<style>  
/* 同上 */  
</style>
  • 第三方库或插件:许多前端框架和库都提供了懒加载的支持,如React的Lazy和Suspense组件、Vue的vue-lazyload插件等。
npm install vue-lazyload --save
// main.js 或类似的入口文件  
import Vue from 'vue';  
import VueLazyload from 'vue-lazyload';  
  
Vue.use(VueLazyload, {  
  preLoad: 1.3,  
  error: 'dist/error.png',  
  loading: 'dist/loading.gif',  
  attempt: 1  
});  
  
// 在你的Vue组件中  
<template>  
  <div>  
    <img v-lazy="'real-image.jpg'" alt="Lazy loaded image">  
  </div>  
</template>
;