CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue-lazyload

Vue.js plugin for lazy-loading images and components with directives, components, and programmatic APIs

Pending
Overview
Eval results
Files

programmatic-api.mddocs/

Programmatic API

Direct access to the lazy loading handler for manual control, event handling, and performance monitoring.

Capabilities

Lazy Handler Access

Access the main lazy loading handler instance through Vue's global properties or injection system.

/**
 * Main lazy loading handler interface
 */
interface VueLazyloadHandler {
  /** Register event listener for lazy loading events */
  $on(event: LazyEventType, callback: VueLazyloadListenEvent): void;
  /** Register one-time event listener */
  $once(event: LazyEventType, callback: VueLazyloadListenEvent): void;
  /** Remove event listener */
  $off(event: LazyEventType, callback?: VueLazyloadListenEvent): void;
  /** Manually trigger lazy load check */
  lazyLoadHandler(): void;
  /** Get performance metrics for all listeners */
  performance(): VueReactiveListener[];
  /** Manually add element for lazy loading */
  add(el: HTMLElement, binding: DirectiveBinding, vnode: VNode): void;
  /** Update element configuration */
  update(el: HTMLElement, binding: DirectiveBinding, vnode?: VNode): void;
  /** Remove element from lazy loading */
  remove(el: HTMLElement): void;
  /** Set loading mode (event or observer) */
  setMode(mode: "event" | "observer"): void;
  /** Add lazy component to queue */
  addLazyBox(vm: LazyComponentInstance): void;
  /** Remove lazy component from queue */
  removeComponent(vm: LazyComponentInstance): void;
}

/**
 * Event types for lazy loading
 */
type LazyEventType = "loading" | "loaded" | "error";

/**
 * Event callback interface
 */
interface VueLazyloadListenEvent {
  (listener: VueReactiveListener, cache: boolean): void;
}

/**
 * Reactive listener representing a lazy-loaded element
 */
interface VueReactiveListener {
  el: Element;
  src: string;
  error: string;
  loading: string;
  bindType: string;
  attempt: number;
  naturalHeight: number;
  naturalWidth: number;
  options: VueLazyloadOptions;
  rect: DOMRect;
  $parent: Element;
  elRenderer: Function;
  performanceData: Performance;
}

/**
 * Lazy component instance for programmatic control
 */
interface LazyComponentInstance {
  el: HTMLElement;
  rect: DOMRect;
  checkInView(): boolean;
  load(): void;
  state: {
    loaded: boolean;
    error: boolean;
    attempt: number;
  };
}

Usage Examples:

import { getCurrentInstance } from "vue";

// Access in composition API
const instance = getCurrentInstance();
const lazyload = instance?.appContext.config.globalProperties.$Lazyload;

// Register event listeners
lazyload?.$on("loaded", (listener, fromCache) => {
  console.log("Image loaded:", listener.src);
  console.log("From cache:", fromCache);
  console.log("Natural dimensions:", listener.naturalWidth, "x", listener.naturalHeight);
});

lazyload?.$on("loading", (listener) => {
  console.log("Loading started:", listener.src);
  console.log("Attempt:", listener.attempt);
});

lazyload?.$on("error", (listener) => {
  console.error("Loading failed:", listener.src);
  console.log("Max attempts reached:", listener.attempt >= listener.options.attempt);
});

// Manual lazy load trigger
const triggerLazyLoad = () => {
  lazyload?.lazyLoadHandler();
};

// Get performance data
const getPerformanceMetrics = () => {
  const metrics = lazyload?.performance() || [];
  return metrics.map(listener => ({
    src: listener.src,
    loadTime: listener.performanceData.loadEnd - listener.performanceData.loadStart,
    totalTime: listener.performanceData.loadEnd - listener.performanceData.init,
  }));
};

Event System

Comprehensive event handling for monitoring lazy loading lifecycle.

/**
 * Performance timing data for loaded images
 */
interface Performance {
  /** Timestamp when listener was initialized */
  init: number;
  /** Timestamp when loading started */
  loadStart: number;
  /** Timestamp when loading completed */
  loadEnd: number;
}

/**
 * Event data passed to event listeners
 */
interface LazyEventData {
  listener: VueReactiveListener;
  fromCache: boolean;
}

Usage Examples:

<script setup>
import { getCurrentInstance, onMounted, onUnmounted } from "vue";

const instance = getCurrentInstance();
const lazyload = instance?.appContext.config.globalProperties.$Lazyload;

// Event handlers
const handleImageLoaded = (listener, cache) => {
  const loadTime = listener.performanceData.loadEnd - listener.performanceData.loadStart;
  console.log(`Image ${listener.src} loaded in ${loadTime}ms (cached: ${cache})`);
  
  // Track analytics
  trackImageLoad({
    src: listener.src,
    loadTime,
    fromCache: cache,
    dimensions: {
      width: listener.naturalWidth,
      height: listener.naturalHeight
    }
  });
};

const handleImageError = (listener, cache) => {
  console.error("Failed to load:", listener.src);
  
  // Report error
  reportImageError({
    src: listener.src,
    attempt: listener.attempt,
    errorFallback: listener.error
  });
};

const handleImageLoading = (listener, cache) => {
  console.log("Starting to load:", listener.src);
  
  // Show loading indicator
  showLoadingIndicator(listener.el);
};

// Lifecycle management
onMounted(() => {
  if (lazyload) {
    lazyload.$on("loaded", handleImageLoaded);
    lazyload.$on("error", handleImageError);
    lazyload.$on("loading", handleImageLoading);
  }
});

onUnmounted(() => {
  if (lazyload) {
    lazyload.$off("loaded", handleImageLoaded);
    lazyload.$off("error", handleImageError);  
    lazyload.$off("loading", handleImageLoading);
  }
});

// Utility functions
const trackImageLoad = (data) => {
  // Send to analytics service
};

const reportImageError = (error) => {
  // Send to error reporting service
};

const showLoadingIndicator = (element) => {
  element.classList.add("loading");
};
</script>

Manual Element Management

Programmatically add, update, and remove elements from lazy loading.

/**
 * Manual element management methods
 */
interface ManualElementControl {
  /** Add element to lazy loading queue */
  add(el: HTMLElement, binding: DirectiveBinding, vnode: VNode): void;
  /** Update element lazy loading configuration */
  update(el: HTMLElement, binding: DirectiveBinding, vnode?: VNode): void;
  /** Remove element from lazy loading */
  remove(el: HTMLElement): void;
}

/**
 * Directive binding simulation for manual control
 */
interface ManualDirectiveBinding {
  value: string | VueLazyloadImageOptions;
  arg?: string;
  modifiers?: Record<string, boolean>;
  instance?: ComponentPublicInstance;
}

Usage Examples:

<script setup>
import { ref, onMounted, getCurrentInstance } from "vue";

const instance = getCurrentInstance();
const lazyload = instance?.appContext.config.globalProperties.$Lazyload;
const imageElement = ref<HTMLElement>();
const dynamicImages = ref<HTMLElement[]>([]);

// Manual element addition
const addImageToLazyLoad = (element: HTMLElement, imageUrl: string) => {
  const binding = {
    value: {
      src: imageUrl,
      loading: "/loading.gif",
      error: "/error.png"
    },
    instance: instance?.proxy
  };
  
  lazyload?.add(element, binding as DirectiveBinding, {} as VNode);
};

// Update image source
const updateImageSource = (element: HTMLElement, newUrl: string) => {
  const binding = {
    value: newUrl,
    instance: instance?.proxy
  };
  
  lazyload?.update(element, binding as DirectiveBinding);
};

// Remove from lazy loading
const removeFromLazyLoad = (element: HTMLElement) => {
  lazyload?.remove(element);
};

// Dynamic image gallery management
const addImageToGallery = (imageUrl: string) => {
  const img = document.createElement("img");
  img.alt = "Dynamic image";
  
  // Add to DOM
  const gallery = document.getElementById("dynamic-gallery");
  gallery?.appendChild(img);
  
  // Add to lazy loading
  addImageToLazyLoad(img, imageUrl);
  
  // Track element
  dynamicImages.value.push(img);
};

const clearGallery = () => {
  dynamicImages.value.forEach(img => {
    removeFromLazyLoad(img);
    img.remove();
  });
  dynamicImages.value = [];
};

// Batch operations
const batchUpdateImages = (updates: Array<{element: HTMLElement, url: string}>) => {
  updates.forEach(({element, url}) => {
    updateImageSource(element, url);
  });
  
  // Trigger manual check after batch updates
  lazyload?.lazyLoadHandler();
};

onMounted(() => {
  // Example: Add initial images
  const initialImages = [
    "/gallery/image1.jpg",
    "/gallery/image2.jpg", 
    "/gallery/image3.jpg"
  ];
  
  initialImages.forEach(url => {
    addImageToGallery(url);
  });
});
</script>

<template>
  <div>
    <button @click="addImageToGallery('/new-image.jpg')">Add Image</button>
    <button @click="clearGallery">Clear Gallery</button>
    <div id="dynamic-gallery"></div>
  </div>
</template>

Performance Monitoring

Monitor and analyze lazy loading performance across your application.

/**
 * Performance monitoring interface
 */
interface PerformanceMonitoring {
  /** Get detailed performance metrics for all listeners */
  performance(): VueReactiveListener[];
  /** Generate performance summary */
  getPerformanceSummary(): PerformanceSummary;
}

/**
 * Performance summary data
 */
interface PerformanceSummary {
  totalImages: number;
  loadedImages: number;
  errorImages: number;
  averageLoadTime: number;
  cacheHitRate: number;
  largestImage: {
    src: string;
    size: { width: number; height: number };
    loadTime: number;
  };
}

Usage Examples:

// Performance monitoring utility
class LazyLoadMonitor {
  private lazyload: VueLazyloadHandler;
  private metrics: Map<string, PerformanceMetric> = new Map();

  constructor(lazyloadHandler: VueLazyloadHandler) {
    this.lazyload = lazyloadHandler;
    this.setupEventListeners();
  }

  private setupEventListeners() {
    this.lazyload.$on("loading", (listener) => {
      this.metrics.set(listener.src, {
        src: listener.src,
        startTime: Date.now(),
        attempt: listener.attempt,
      });
    });

    this.lazyload.$on("loaded", (listener, fromCache) => {
      const metric = this.metrics.get(listener.src);
      if (metric) {
        metric.endTime = Date.now();
        metric.loadTime = metric.endTime - metric.startTime;
        metric.fromCache = fromCache;
        metric.dimensions = {
          width: listener.naturalWidth,
          height: listener.naturalHeight,
        };
      }
    });

    this.lazyload.$on("error", (listener) => {
      const metric = this.metrics.get(listener.src);
      if (metric) {
        metric.error = true;
        metric.endTime = Date.now();
      }
    });
  }

  getReport(): PerformanceReport {
    const allMetrics = Array.from(this.metrics.values());
    const successfulLoads = allMetrics.filter(m => !m.error && m.loadTime);
    
    return {
      totalRequests: allMetrics.length,
      successfulLoads: successfulLoads.length,
      errorCount: allMetrics.filter(m => m.error).length,
      averageLoadTime: successfulLoads.reduce((sum, m) => sum + (m.loadTime || 0), 0) / successfulLoads.length,
      cacheHitRate: successfulLoads.filter(m => m.fromCache).length / successfulLoads.length,
      slowestImage: successfulLoads.reduce((slowest, current) => 
        (current.loadTime || 0) > (slowest.loadTime || 0) ? current : slowest
      ),
      largestImage: successfulLoads.reduce((largest, current) => {
        const currentSize = (current.dimensions?.width || 0) * (current.dimensions?.height || 0);
        const largestSize = (largest.dimensions?.width || 0) * (largest.dimensions?.height || 0);
        return currentSize > largestSize ? current : largest;
      }),
    };
  }

  exportMetrics(): string {
    return JSON.stringify(this.getReport(), null, 2);
  }
}

interface PerformanceMetric {
  src: string;
  startTime: number;
  endTime?: number;
  loadTime?: number;
  fromCache?: boolean;
  attempt: number;
  error?: boolean;
  dimensions?: { width: number; height: number };
}

interface PerformanceReport {
  totalRequests: number;
  successfulLoads: number;
  errorCount: number;
  averageLoadTime: number;
  cacheHitRate: number;
  slowestImage: PerformanceMetric;
  largestImage: PerformanceMetric;
}

// Usage
const monitor = new LazyLoadMonitor(lazyload);

// Get performance report
setTimeout(() => {
  const report = monitor.getReport();
  console.log("Lazy loading performance:", report);
  
  // Export for analysis
  const metrics = monitor.exportMetrics();
  localStorage.setItem("lazyload-metrics", metrics);
}, 10000);

Mode Management

Control lazy loading detection mode between event-based and IntersectionObserver-based approaches.

/**
 * Mode management interface
 */
interface ModeManagement {
  /** Set loading detection mode */
  setMode(mode: "event" | "observer"): void;
  /** Current active mode */
  mode: string;
}

Usage Examples:

// Dynamic mode switching based on performance
const optimizeLazyLoadMode = () => {
  const isMobile = window.innerWidth < 768;
  const hasIntersectionObserver = "IntersectionObserver" in window;
  const isSlowConnection = navigator.connection?.effectiveType === "slow-2g";

  if (hasIntersectionObserver && (isMobile || isSlowConnection)) {
    // Use observer mode for better performance on mobile/slow connections
    lazyload?.setMode("observer");
    console.log("Switched to IntersectionObserver mode");
  } else {
    // Use event mode for desktop with fast connections
    lazyload?.setMode("event");
    console.log("Switched to event-based mode");
  }
};

// Switch modes based on scroll performance
let scrollPerformance = 0;
const measureScrollPerformance = () => {
  const start = performance.now();
  
  const scrollHandler = () => {
    const end = performance.now();
    scrollPerformance = end - start;
    
    // If scroll events are slow, switch to observer mode
    if (scrollPerformance > 16 && lazyload?.mode === "event") {
      lazyload.setMode("observer");
    }
    
    window.removeEventListener("scroll", scrollHandler);
  };
  
  window.addEventListener("scroll", scrollHandler, { once: true });
  
  // Trigger a scroll event
  window.scrollBy(0, 1);
};

// Initialize optimal mode
optimizeLazyLoadMode();
measureScrollPerformance();

Install with Tessl CLI

npx tessl i tessl/npm-vue-lazyload

docs

components.md

directives.md

index.md

plugin-installation.md

programmatic-api.md

tile.json