Vue 自定义指令 v-lazy 基于 IntersectionObserver 实现图片懒加载,预加载进入视口前100px的图片,支持响应式、背景图、降级兼容及加载状态管理,有效减少首屏时间20%~40%。
用 Vue 自定义指令实现图片懒加载,核心是监听元素进入视口时才加载真实图片,避免首屏大量图片阻塞渲染。关键不在写多少代码,而在准确判断可见性、处理加载状态、兼顾兼容性和用户体验。
现代浏览器推荐使用 IntersectionObserver 替代 scroll + getBoundingClientRect 手动计算,性能更好、代码更简洁:
rootMargin: '0px 0px 100px 0px',让图片在进入视口前 100px 就开始加载,避免滚动过快时出现空白unobserve 避免重复触发scroll 事件 + throttle(如 Lodash 的 debounce),或引入 polyfill自定义指令 v-lazy 要接管图片的生命周期:
data-src 属性里,src 初始为空或设为占位图(如 base64 小灰图)data-src 值赋给 src,并移除 data-src
loading 类名或绑定 v-bind:class="{ 'is-loading': !loaded }",配合 CSS 实现骨架屏或淡入效果is-loaded 类;失败时可 fallback 到默认图或显示错误提示实际项目中常需处理 <picture>、srcset 或元素背景图:
立即学习“前端免费学习笔记(深入)”;
<picture>,指令应遍历其内部 <source> 标签,把 data-srcset、data-media 等属性同步替换为 srcset、media
el.style.backgroundImage = `url(${src})` 设置,并注意 URL 编码与引号包裹(如 url("${src}"))v-lazy:bg 表示背景图模式,v-lazy:responsive 启用 srcset 支持不是所有图片都需要懒加载:
main.js 中全局注册指令,但通过 binding.arg 或 binding.modifiers 控制行为,例如 v-lazy.immediate 强制立即加载v-if="$route.name !== 'home'" 等逻辑规避水合 mismatch不复杂但容易忽略:记得给懒加载图片设置固定宽高或 aspect-ratio,防止加载时布局抖动。用好 v-lazy,首屏时间通常能减少 20%~40%,用户感知更明显。