-
首先需要安装依赖
npm i @vueuse/core -
需要用到@vueuse/core的 API useIntersectionObserver
const { stop } = useIntersectionObserver( // target表示通过ref获取到的组件对象或Dom对象 target, // isIntersecting 代表组件对象是否进入可视区域 ([{ isIntersecting }], observerElement) =>{ if(isIntersecting) { // 进入可视区域,发请求,展示图片 } }, ) -
实现步骤
- 实现一个空的插件
export const directivePlugin = {
install (app) {
}
}
- 实现一个空的指令
app.directive('imgLazy', {
mounted(el,binding){
}
})
- 实现懒加载的逻辑,注册插件
import { useIntersectionObserver } from '@vueuse/core'
export const directivePlugin = {
install (app) {
// console.log('app实参', app)
app.directive('imgLazy', {
// inserted:被绑定元素插入父节点时调用,vue2用的是inserted,vue3用的mounted
// 第一个参数是dom,第二个参数是binding的dom
mounted (el, binding) {
const { stop } = useIntersectionObserver(
el,
// isIntersecting 代表组件对象是否进入可视区域
([{ isIntersecting }], observerElement) => {
if (isIntersecting) {
// 如果图片滚动到视口,就修改src属性,发请求,实现懒加载
el.src = binding.value
// stop 是停止监听的方法
// 优化:如果图片加载出来了,就不再进行懒加载
stop()
}
}
)
}
})
}
}
- 注册到 全局 main.js
// 空插件注册
import { directivePlugin } from '@/directives'
createApp(App).use(store).use(router).use(directivePlugin).mount('#app')
- 在img标签上使用自定义指令
<ul class="goods-list">
<li v-for="item in newList" :key="item.id">
<RouterLink :to="`/good/${item.id}`">
<img v-imgLazy="item.picture" alt="" />
<p class="name">{{ item.name }}</p>
<p class="price">¥{{ item.price }}</p>
</RouterLink>
</li>
</ul>