vue3图片懒加载

背景

界面很长,屏幕不能一下装下所有内容,如果以进入首页就把所有内容都加载完的话所需时间较长,会影响用户体验,所以可以当用户浏览到时再去加载。

代码

新建index.ts文件

src下新建directives文件夹,并新建Index.ts文件

javascript 复制代码
import { useIntersectionObserver } from '@vueuse/core'
import { install } from 'element-plus'

export const lazyPlugin = {
    install(app){
        // 懒加载指令逻辑

        // 定义全局指令
        // 这个属于图片懒加载部分
        app.directive('img-lazy',{
            mounted(el, binding){
                // el: 指令绑定的那个元素 img
                // binding: binding.value 指令等于号后面绑定的表达式的值 图片url
                const {stop} =useIntersectionObserver(
                    el,
                    ([{isIntersecting}]) => {
                        // 第一次赋值之后,就不用再监听了 -> stop()
                        // 防止内存的浪费
                        if(isIntersecting){
                            el.src = binding.value
                            stop()
                        }
                    },
                )
            }
        })
    }
}

修改main.ts文件

javascript 复制代码
import './assets/main.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

// 引入初始化样式文件
import '@/styles/common.scss'
// 引入图片延迟加载
import { lazyPlugin } from '@/directives/index'

const app = createApp(App)

app.use(createPinia())
app.use(router)
// 使用图片延迟加载插件
app.use(lazyPlugin)

app.mount('#app')

HomeHot.vue

index.ts文件中定义的名字叫img-lazy,在这里使用的时候用 v-img-lazy,后面跟图片对应路径

html 复制代码
<script setup lang="ts" name="HomeHot">
import HomePanel from './HomePanel.vue'
import { getHotAPI } from '@/apis/home'
import { onMounted, ref } from 'vue'

const hotList = ref([])
const getHotList = async () => {
    const res = await getHotAPI()
    console.log(res)
    hotList.value = res.data.result
}
onMounted(() => getHotList())


</script>

<template>
    <HomePanel title="人气推荐" sub-title="人气爆款 不容错过">
        <ul class="goods-list">
            <li v-for="item in hotList" :key="item.id">
                <RouterLink to="/">
                    <img v-img-lazy="item.picture" alt="">
                    <p class="name">{{ item.title }}</p>
                    <p class="desc">{{ item.alt }}</p>
                </RouterLink>
            </li>
        </ul>
    </HomePanel>
</template>

<style scoped lang='scss'>
.goods-list {
    display: flex;
    justify-content: space-between;
    height: 426px;

    li {
        width: 306px;
        height: 406px;
        transition: all .5s;

        &:hover {
            transform: translate3d(0, -3px, 0);
            box-shadow: 0 3px 8px rgb(0 0 0 / 20%);
        }

        img {
            width: 306px;
            height: 306px;
        }

        p {
            font-size: 22px;
            padding-top: 12px;
            text-align: center;
        }

        .desc {
            color: #999;
            font-size: 18px;
        }
    }
}
</style>
相关推荐
何何____5 小时前
Vue 全局事件总线详解
前端·javascript·vue.js
EatFan5 小时前
Go语言全栈实战:基于 Gin + Vue + JWT + RBAC 从零搭建前后端分离权限管理系统
vue.js·golang·go·vue·gin·jwt·rbac
陈拉斯7 小时前
Vue SPA 站百度收录“全军覆没“?一次预渲染抢救的完整实战(2026 踩坑版)
vue.js
一 乐18 小时前
动漫书销售商城|基于springboot + vue动漫书销售商城(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕业设计
wengad20 小时前
从 wangEditor 迁到 wangEditor-next
前端·javascript·vue.js
FYKJ_20101 天前
django电影推荐系统55066-计算机课程设计、毕业设计
vue.js·spring boot·python·mysql·typescript·spark·django
qq_316837751 天前
阿里云百炼 fun-asr-realtime uniapp vue3 调用
javascript·vue.js·uni-app
李剑一1 天前
AntDesign老版本没有月份和年份区间选择组件?我封装了一个完美版,附源码!
前端·vue.js
计算机毕设定制辅导-无忧学长1 天前
《基于Spring Boot的减脂轻食购物网站》
java·vue.js·spring boot·后端·减脂轻食购物网站