Vue-Lazyload
Vue-Lazyload is a Vue.js module designed for efficiently lazy-loading images within Vue 3 applications. As of version 3.0.0, it is specifically tailored for Vue 3, offering a lightweight and powerful solution to improve initial page load performance by deferring image loading until they enter the viewport. It provides a simple directive-based API (`v-lazy`) for individual images and supports managing groups of images within a container using `v-lazy-container`. The library offers customization through options for custom loading and error placeholders, configurable pre-loading distances, and various event listeners. While historical versions targeted Vue 1.x and 2.x, the current major release, v3.0.0, represents a significant shift to Vue 3, necessitating changes in application initialization. The project's release cadence appears to be irregular, with notable intervals between major version updates.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'directive') OR [Vue warn]: Failed to resolve directive: lazy
cause Vue-Lazyload plugin was not properly installed on the Vue application instance.fixEnsure `app.use(VueLazyload, options)` is called after `createApp(App)` and before `app.mount('#app')` in your Vue 3 application's entry file (e.g., `main.ts`). -
Image src is blank or broken when using v-lazy
cause The image `src` or `data-src` value is incorrect, inaccessible, or the `loading` and `error` placeholders are not resolving.fixDouble-check image paths for `v-lazy` and ensure that placeholder images defined in plugin options (`loading`, `error`) are correctly imported or provided with absolute/root-relative paths that your build system can resolve. For `v-lazy-container`, ensure `data-src` is used on `<img>` tags. -
Images not lazy-loading; all load on page render
cause The `listenEvents` option might be misconfigured, `IntersectionObserver` is not working/polyfilled, or the images are already in the viewport due to small content or incorrect `preLoad` value.fixVerify that `preLoad` is set to a reasonable value (default is 1.3). Ensure there is enough scrollable content for images to be initially off-screen. If targeting older browsers, ensure `IntersectionObserver` is polyfilled. Check the `listenEvents` array in the options for any missing critical events like 'scroll'.
Warnings
- breaking Vue-Lazyload v3.0.0 is built exclusively for Vue 3. Projects migrating from Vue 2 (which used vue-lazyload v1.x) must update their application initialization logic from `new Vue({ ... })` and `Vue.use(VueLazyload)` to the Vue 3 `createApp` instance API (e.g., `createApp(App).use(VueLazyload)`). The global Vue instance is no longer directly mutable.
- breaking Modern Vue 3 applications and `vue-lazyload` v3.x are designed for ES Modules (`import`). Using CommonJS `require('vue-lazyload')` directly will likely lead to module resolution errors or unexpected behavior in standard Vue CLI/Vite setups. Ensure you use `import` statements.
- gotcha When providing `loading` and `error` image paths as plugin options (e.g., in `main.ts`), ensure they are correctly resolved by your build tool (Webpack, Vite). Simple string literals for relative paths might not be processed correctly unless explicitly imported or served from a static public folder.
- gotcha The library leverages `IntersectionObserver` for efficient lazy loading when available. In environments lacking native `IntersectionObserver` support (e.g., older browsers like IE or some specific WebViews), it falls back to less performant scroll event listening. This can lead to less precise loading or decreased performance.
Install
-
npm install vue-lazyload -
yarn add vue-lazyload -
pnpm add vue-lazyload
Imports
- VueLazyload
const VueLazyload = require('vue-lazyload')import VueLazyload from 'vue-lazyload'
- v-lazy (directive)
<img :src="imageSrc" v-lazy>
<img v-lazy="imageSrc">
- v-lazy-container (directive)
<div v-lazy-container> <img src="//example.com/img.jpg"> </div>
<div v-lazy-container="{ selector: 'img', error: 'error.jpg' }"> <img data-src="//example.com/img.jpg"> </div>
Quickstart
import { createApp } from 'vue';
import App from './App.vue';
import VueLazyload from 'vue-lazyload';
// Import images for placeholders, ensuring they are correctly processed by your bundler
import loadingGif from './assets/loading.gif';
import errorGif from './assets/error.gif';
const app = createApp(App);
app.use(VueLazyload, {
preLoad: 1.3, // Pre-load 1.3 times the viewport height
error: errorGif, // Image to show on error
loading: loadingGif, // Image to show while loading
attempt: 1 // Number of attempts to load the image
});
app.mount('#app');
// src/App.vue
<template>
<div>
<h1>Lazy Loaded Images</h1>
<div v-for="n in 100" :key="n" class="image-wrapper">
<img v-lazy="`https://picsum.photos/id/${n + 10}/400/300`" alt="Placeholder Image">
</div>
<h2>Lazy Loaded Raw HTML Images</h2>
<div v-lazy-container="{ selector: 'img', error: '/placeholder_error.jpg', loading: '/placeholder_loading.gif' }" class="raw-html-container">
<img data-src="https://picsum.photos/id/1000/400/300" alt="Raw HTML Image 1">
<img data-src="https://picsum.photos/id/1001/400/300" alt="Raw HTML Image 2">
</div>
</div>
</template>
<style>
.image-wrapper {
height: 300px; /* Give some height for scrolling */
margin-bottom: 20px;
display: flex;
justify-content: center;
align-items: center;
background-color: #f0f0f0;
}
img {
max-width: 100%;
height: auto;
display: block;
}
.raw-html-container img {
height: 200px;
width: 300px;
object-fit: cover;
margin: 10px;
}
</style>