Skip to content

lazy 图片懒加载指令

用于懒加载图片或背景图,在元素进入视口时再设置 src/srcsetbackground-image,支持回调与一次性加载。

安装与引入

按需导入(推荐)

ts
import { VLazy } from '@cuixingjian/cui-utils'

全局注册

ts
import { createApp } from 'vue'
import { VLazy } from '@cuixingjian/cui-utils'

const app = createApp(App)
app.directive('lazy', VLazy)
app.mount('#app')

局部注册

vue
<script setup lang="ts">
import { VLazy as vLazy } from '@cuixingjian/cui-utils'
</script>

<template>
  <img v-lazy data-src="image.jpg" />
</template>

效果演示

基础用法

滚动页面查看图片懒加载效果。

使用代码

使用 data-src 属性:

vue
<template>
  <img 
    src="placeholder.png" 
    data-src="https://example.com/real.jpg" 
    v-lazy 
  />
</template>

使用配置对象:

vue
<template>
  <img v-lazy="{ src: 'https://example.com/image.jpg' }" />
</template>

懒加载背景图:

vue
<template>
  <div 
    v-lazy="{ bg: 'https://example.com/bg.jpg' }"
    style="min-height: 200px; background-size: cover;"
  >
    内容
  </div>
</template>

带回调:

vue
<script setup lang="ts">
function onLoad(el: Element) {
  console.log('图片加载完成', el)
}
</script>

<template>
  <img v-lazy="{ src: 'image.jpg', onLoad }" />
</template>

API 说明

指令值类型

类型说明示例
string直接传入图片地址v-lazy="'image.jpg'"
Object传入配置对象v-lazy="{ src: 'image.jpg' }"

配置选项 (LazyDirectiveOptions)

参数类型默认值说明
srcstring图片真实地址(不传则读取 data-src)
srcsetstring图片 srcset(不传则读取 data-srcset)
bgstring背景图地址(不传则读取 data-bg)
rootElement | nullnullIntersectionObserver 的根元素
rootMarginstring'0px'视口边距,如 '200px 0px'
thresholdnumber | number[]0触发阈值(0-1)
oncebooleantrue是否仅加载一次
srcAttrstring'data-src'自定义读取的属性名
srcsetAttrstring'data-srcset'自定义读取的属性名
bgAttrstring'data-bg'自定义读取的属性名
beforeLoad(el: Element) => void加载前回调
onLoad(el: Element) => void加载成功回调
onError(el: Element, error: any) => void加载失败回调

注意事项

IntersectionObserver

  • 使用 IntersectionObserver API 实现懒加载
  • 不支持的环境会直接加载图片
  • 可通过 threshold 控制触发时机

占位处理

建议在真实资源加载前设置占位:

  • 使用占位图片
  • 添加骨架屏
  • 使用模糊效果(blur)
  • 设置背景色

性能优化

  • once: true 避免重复加载
  • 使用 rootMargin 提前加载
  • 合理设置 threshold

常见场景

  • 图片列表:大量图片懒加载
  • 长页面:分屏加载内容
  • 背景图:懒加载背景图片
  • 响应式图片:使用 srcset

源码展示

展开查看完整源码
ts
import type { Directive } from 'vue'
import { withInstallDirective } from '../install'

export interface LazyDirectiveOptions {
  root?: Element | null
  rootMargin?: string
  threshold?: number | number[]
  src?: string
  srcset?: string
  bg?: string
  srcAttr?: string
  srcsetAttr?: string
  bgAttr?: string
  beforeLoad?: (el: Element) => void
  onLoad?: (el: Element) => void
  onError?: (el: Element, error: any) => void
  once?: boolean
}

// 详见 packages/utils/directives/lazy.ts
export const VLazy = withInstallDirective(lazy, 'lazy')