0
# Programmatic API
1
2
Direct access to the lazy loading handler for manual control, event handling, and performance monitoring.
3
4
## Capabilities
5
6
### Lazy Handler Access
7
8
Access the main lazy loading handler instance through Vue's global properties or injection system.
9
10
```typescript { .api }
11
/**
12
* Main lazy loading handler interface
13
*/
14
interface VueLazyloadHandler {
15
/** Register event listener for lazy loading events */
16
$on(event: LazyEventType, callback: VueLazyloadListenEvent): void;
17
/** Register one-time event listener */
18
$once(event: LazyEventType, callback: VueLazyloadListenEvent): void;
19
/** Remove event listener */
20
$off(event: LazyEventType, callback?: VueLazyloadListenEvent): void;
21
/** Manually trigger lazy load check */
22
lazyLoadHandler(): void;
23
/** Get performance metrics for all listeners */
24
performance(): VueReactiveListener[];
25
/** Manually add element for lazy loading */
26
add(el: HTMLElement, binding: DirectiveBinding, vnode: VNode): void;
27
/** Update element configuration */
28
update(el: HTMLElement, binding: DirectiveBinding, vnode?: VNode): void;
29
/** Remove element from lazy loading */
30
remove(el: HTMLElement): void;
31
/** Set loading mode (event or observer) */
32
setMode(mode: "event" | "observer"): void;
33
/** Add lazy component to queue */
34
addLazyBox(vm: LazyComponentInstance): void;
35
/** Remove lazy component from queue */
36
removeComponent(vm: LazyComponentInstance): void;
37
}
38
39
/**
40
* Event types for lazy loading
41
*/
42
type LazyEventType = "loading" | "loaded" | "error";
43
44
/**
45
* Event callback interface
46
*/
47
interface VueLazyloadListenEvent {
48
(listener: VueReactiveListener, cache: boolean): void;
49
}
50
51
/**
52
* Reactive listener representing a lazy-loaded element
53
*/
54
interface VueReactiveListener {
55
el: Element;
56
src: string;
57
error: string;
58
loading: string;
59
bindType: string;
60
attempt: number;
61
naturalHeight: number;
62
naturalWidth: number;
63
options: VueLazyloadOptions;
64
rect: DOMRect;
65
$parent: Element;
66
elRenderer: Function;
67
performanceData: Performance;
68
}
69
70
/**
71
* Lazy component instance for programmatic control
72
*/
73
interface LazyComponentInstance {
74
el: HTMLElement;
75
rect: DOMRect;
76
checkInView(): boolean;
77
load(): void;
78
state: {
79
loaded: boolean;
80
error: boolean;
81
attempt: number;
82
};
83
}
84
```
85
86
**Usage Examples:**
87
88
```typescript
89
import { getCurrentInstance } from "vue";
90
91
// Access in composition API
92
const instance = getCurrentInstance();
93
const lazyload = instance?.appContext.config.globalProperties.$Lazyload;
94
95
// Register event listeners
96
lazyload?.$on("loaded", (listener, fromCache) => {
97
console.log("Image loaded:", listener.src);
98
console.log("From cache:", fromCache);
99
console.log("Natural dimensions:", listener.naturalWidth, "x", listener.naturalHeight);
100
});
101
102
lazyload?.$on("loading", (listener) => {
103
console.log("Loading started:", listener.src);
104
console.log("Attempt:", listener.attempt);
105
});
106
107
lazyload?.$on("error", (listener) => {
108
console.error("Loading failed:", listener.src);
109
console.log("Max attempts reached:", listener.attempt >= listener.options.attempt);
110
});
111
112
// Manual lazy load trigger
113
const triggerLazyLoad = () => {
114
lazyload?.lazyLoadHandler();
115
};
116
117
// Get performance data
118
const getPerformanceMetrics = () => {
119
const metrics = lazyload?.performance() || [];
120
return metrics.map(listener => ({
121
src: listener.src,
122
loadTime: listener.performanceData.loadEnd - listener.performanceData.loadStart,
123
totalTime: listener.performanceData.loadEnd - listener.performanceData.init,
124
}));
125
};
126
```
127
128
### Event System
129
130
Comprehensive event handling for monitoring lazy loading lifecycle.
131
132
```typescript { .api }
133
/**
134
* Performance timing data for loaded images
135
*/
136
interface Performance {
137
/** Timestamp when listener was initialized */
138
init: number;
139
/** Timestamp when loading started */
140
loadStart: number;
141
/** Timestamp when loading completed */
142
loadEnd: number;
143
}
144
145
/**
146
* Event data passed to event listeners
147
*/
148
interface LazyEventData {
149
listener: VueReactiveListener;
150
fromCache: boolean;
151
}
152
```
153
154
**Usage Examples:**
155
156
```vue
157
<script setup>
158
import { getCurrentInstance, onMounted, onUnmounted } from "vue";
159
160
const instance = getCurrentInstance();
161
const lazyload = instance?.appContext.config.globalProperties.$Lazyload;
162
163
// Event handlers
164
const handleImageLoaded = (listener, cache) => {
165
const loadTime = listener.performanceData.loadEnd - listener.performanceData.loadStart;
166
console.log(`Image ${listener.src} loaded in ${loadTime}ms (cached: ${cache})`);
167
168
// Track analytics
169
trackImageLoad({
170
src: listener.src,
171
loadTime,
172
fromCache: cache,
173
dimensions: {
174
width: listener.naturalWidth,
175
height: listener.naturalHeight
176
}
177
});
178
};
179
180
const handleImageError = (listener, cache) => {
181
console.error("Failed to load:", listener.src);
182
183
// Report error
184
reportImageError({
185
src: listener.src,
186
attempt: listener.attempt,
187
errorFallback: listener.error
188
});
189
};
190
191
const handleImageLoading = (listener, cache) => {
192
console.log("Starting to load:", listener.src);
193
194
// Show loading indicator
195
showLoadingIndicator(listener.el);
196
};
197
198
// Lifecycle management
199
onMounted(() => {
200
if (lazyload) {
201
lazyload.$on("loaded", handleImageLoaded);
202
lazyload.$on("error", handleImageError);
203
lazyload.$on("loading", handleImageLoading);
204
}
205
});
206
207
onUnmounted(() => {
208
if (lazyload) {
209
lazyload.$off("loaded", handleImageLoaded);
210
lazyload.$off("error", handleImageError);
211
lazyload.$off("loading", handleImageLoading);
212
}
213
});
214
215
// Utility functions
216
const trackImageLoad = (data) => {
217
// Send to analytics service
218
};
219
220
const reportImageError = (error) => {
221
// Send to error reporting service
222
};
223
224
const showLoadingIndicator = (element) => {
225
element.classList.add("loading");
226
};
227
</script>
228
```
229
230
### Manual Element Management
231
232
Programmatically add, update, and remove elements from lazy loading.
233
234
```typescript { .api }
235
/**
236
* Manual element management methods
237
*/
238
interface ManualElementControl {
239
/** Add element to lazy loading queue */
240
add(el: HTMLElement, binding: DirectiveBinding, vnode: VNode): void;
241
/** Update element lazy loading configuration */
242
update(el: HTMLElement, binding: DirectiveBinding, vnode?: VNode): void;
243
/** Remove element from lazy loading */
244
remove(el: HTMLElement): void;
245
}
246
247
/**
248
* Directive binding simulation for manual control
249
*/
250
interface ManualDirectiveBinding {
251
value: string | VueLazyloadImageOptions;
252
arg?: string;
253
modifiers?: Record<string, boolean>;
254
instance?: ComponentPublicInstance;
255
}
256
```
257
258
**Usage Examples:**
259
260
```vue
261
<script setup>
262
import { ref, onMounted, getCurrentInstance } from "vue";
263
264
const instance = getCurrentInstance();
265
const lazyload = instance?.appContext.config.globalProperties.$Lazyload;
266
const imageElement = ref<HTMLElement>();
267
const dynamicImages = ref<HTMLElement[]>([]);
268
269
// Manual element addition
270
const addImageToLazyLoad = (element: HTMLElement, imageUrl: string) => {
271
const binding = {
272
value: {
273
src: imageUrl,
274
loading: "/loading.gif",
275
error: "/error.png"
276
},
277
instance: instance?.proxy
278
};
279
280
lazyload?.add(element, binding as DirectiveBinding, {} as VNode);
281
};
282
283
// Update image source
284
const updateImageSource = (element: HTMLElement, newUrl: string) => {
285
const binding = {
286
value: newUrl,
287
instance: instance?.proxy
288
};
289
290
lazyload?.update(element, binding as DirectiveBinding);
291
};
292
293
// Remove from lazy loading
294
const removeFromLazyLoad = (element: HTMLElement) => {
295
lazyload?.remove(element);
296
};
297
298
// Dynamic image gallery management
299
const addImageToGallery = (imageUrl: string) => {
300
const img = document.createElement("img");
301
img.alt = "Dynamic image";
302
303
// Add to DOM
304
const gallery = document.getElementById("dynamic-gallery");
305
gallery?.appendChild(img);
306
307
// Add to lazy loading
308
addImageToLazyLoad(img, imageUrl);
309
310
// Track element
311
dynamicImages.value.push(img);
312
};
313
314
const clearGallery = () => {
315
dynamicImages.value.forEach(img => {
316
removeFromLazyLoad(img);
317
img.remove();
318
});
319
dynamicImages.value = [];
320
};
321
322
// Batch operations
323
const batchUpdateImages = (updates: Array<{element: HTMLElement, url: string}>) => {
324
updates.forEach(({element, url}) => {
325
updateImageSource(element, url);
326
});
327
328
// Trigger manual check after batch updates
329
lazyload?.lazyLoadHandler();
330
};
331
332
onMounted(() => {
333
// Example: Add initial images
334
const initialImages = [
335
"/gallery/image1.jpg",
336
"/gallery/image2.jpg",
337
"/gallery/image3.jpg"
338
];
339
340
initialImages.forEach(url => {
341
addImageToGallery(url);
342
});
343
});
344
</script>
345
346
<template>
347
<div>
348
<button @click="addImageToGallery('/new-image.jpg')">Add Image</button>
349
<button @click="clearGallery">Clear Gallery</button>
350
<div id="dynamic-gallery"></div>
351
</div>
352
</template>
353
```
354
355
### Performance Monitoring
356
357
Monitor and analyze lazy loading performance across your application.
358
359
```typescript { .api }
360
/**
361
* Performance monitoring interface
362
*/
363
interface PerformanceMonitoring {
364
/** Get detailed performance metrics for all listeners */
365
performance(): VueReactiveListener[];
366
/** Generate performance summary */
367
getPerformanceSummary(): PerformanceSummary;
368
}
369
370
/**
371
* Performance summary data
372
*/
373
interface PerformanceSummary {
374
totalImages: number;
375
loadedImages: number;
376
errorImages: number;
377
averageLoadTime: number;
378
cacheHitRate: number;
379
largestImage: {
380
src: string;
381
size: { width: number; height: number };
382
loadTime: number;
383
};
384
}
385
```
386
387
**Usage Examples:**
388
389
```typescript
390
// Performance monitoring utility
391
class LazyLoadMonitor {
392
private lazyload: VueLazyloadHandler;
393
private metrics: Map<string, PerformanceMetric> = new Map();
394
395
constructor(lazyloadHandler: VueLazyloadHandler) {
396
this.lazyload = lazyloadHandler;
397
this.setupEventListeners();
398
}
399
400
private setupEventListeners() {
401
this.lazyload.$on("loading", (listener) => {
402
this.metrics.set(listener.src, {
403
src: listener.src,
404
startTime: Date.now(),
405
attempt: listener.attempt,
406
});
407
});
408
409
this.lazyload.$on("loaded", (listener, fromCache) => {
410
const metric = this.metrics.get(listener.src);
411
if (metric) {
412
metric.endTime = Date.now();
413
metric.loadTime = metric.endTime - metric.startTime;
414
metric.fromCache = fromCache;
415
metric.dimensions = {
416
width: listener.naturalWidth,
417
height: listener.naturalHeight,
418
};
419
}
420
});
421
422
this.lazyload.$on("error", (listener) => {
423
const metric = this.metrics.get(listener.src);
424
if (metric) {
425
metric.error = true;
426
metric.endTime = Date.now();
427
}
428
});
429
}
430
431
getReport(): PerformanceReport {
432
const allMetrics = Array.from(this.metrics.values());
433
const successfulLoads = allMetrics.filter(m => !m.error && m.loadTime);
434
435
return {
436
totalRequests: allMetrics.length,
437
successfulLoads: successfulLoads.length,
438
errorCount: allMetrics.filter(m => m.error).length,
439
averageLoadTime: successfulLoads.reduce((sum, m) => sum + (m.loadTime || 0), 0) / successfulLoads.length,
440
cacheHitRate: successfulLoads.filter(m => m.fromCache).length / successfulLoads.length,
441
slowestImage: successfulLoads.reduce((slowest, current) =>
442
(current.loadTime || 0) > (slowest.loadTime || 0) ? current : slowest
443
),
444
largestImage: successfulLoads.reduce((largest, current) => {
445
const currentSize = (current.dimensions?.width || 0) * (current.dimensions?.height || 0);
446
const largestSize = (largest.dimensions?.width || 0) * (largest.dimensions?.height || 0);
447
return currentSize > largestSize ? current : largest;
448
}),
449
};
450
}
451
452
exportMetrics(): string {
453
return JSON.stringify(this.getReport(), null, 2);
454
}
455
}
456
457
interface PerformanceMetric {
458
src: string;
459
startTime: number;
460
endTime?: number;
461
loadTime?: number;
462
fromCache?: boolean;
463
attempt: number;
464
error?: boolean;
465
dimensions?: { width: number; height: number };
466
}
467
468
interface PerformanceReport {
469
totalRequests: number;
470
successfulLoads: number;
471
errorCount: number;
472
averageLoadTime: number;
473
cacheHitRate: number;
474
slowestImage: PerformanceMetric;
475
largestImage: PerformanceMetric;
476
}
477
478
// Usage
479
const monitor = new LazyLoadMonitor(lazyload);
480
481
// Get performance report
482
setTimeout(() => {
483
const report = monitor.getReport();
484
console.log("Lazy loading performance:", report);
485
486
// Export for analysis
487
const metrics = monitor.exportMetrics();
488
localStorage.setItem("lazyload-metrics", metrics);
489
}, 10000);
490
```
491
492
### Mode Management
493
494
Control lazy loading detection mode between event-based and IntersectionObserver-based approaches.
495
496
```typescript { .api }
497
/**
498
* Mode management interface
499
*/
500
interface ModeManagement {
501
/** Set loading detection mode */
502
setMode(mode: "event" | "observer"): void;
503
/** Current active mode */
504
mode: string;
505
}
506
```
507
508
**Usage Examples:**
509
510
```typescript
511
// Dynamic mode switching based on performance
512
const optimizeLazyLoadMode = () => {
513
const isMobile = window.innerWidth < 768;
514
const hasIntersectionObserver = "IntersectionObserver" in window;
515
const isSlowConnection = navigator.connection?.effectiveType === "slow-2g";
516
517
if (hasIntersectionObserver && (isMobile || isSlowConnection)) {
518
// Use observer mode for better performance on mobile/slow connections
519
lazyload?.setMode("observer");
520
console.log("Switched to IntersectionObserver mode");
521
} else {
522
// Use event mode for desktop with fast connections
523
lazyload?.setMode("event");
524
console.log("Switched to event-based mode");
525
}
526
};
527
528
// Switch modes based on scroll performance
529
let scrollPerformance = 0;
530
const measureScrollPerformance = () => {
531
const start = performance.now();
532
533
const scrollHandler = () => {
534
const end = performance.now();
535
scrollPerformance = end - start;
536
537
// If scroll events are slow, switch to observer mode
538
if (scrollPerformance > 16 && lazyload?.mode === "event") {
539
lazyload.setMode("observer");
540
}
541
542
window.removeEventListener("scroll", scrollHandler);
543
};
544
545
window.addEventListener("scroll", scrollHandler, { once: true });
546
547
// Trigger a scroll event
548
window.scrollBy(0, 1);
549
};
550
551
// Initialize optimal mode
552
optimizeLazyLoadMode();
553
measureScrollPerformance();
554
```