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 小时前
我做了一个本地优先的 AI 图片工作台:Loomora v1.0.0 正式发布
前端·javascript·vue.js
Flynt8 小时前
我扒了Fantastic-admin 6.0的源码,聊聊"AI时代版本答案"这个称号
vue.js·ai编程·cursor
码艺-Alimjan9 小时前
Vue项目源码备份最佳实践:无视node_modules,打包体积仅2MB
前端·javascript·vue.js
风月说与山鬼11 小时前
十二、Vue插件
前端·vue.js
风月说与山鬼17 小时前
四、浏览器存储
前端·vue.js
阿懂在掘金17 小时前
记录四年前的一次前端项目权限方案改造
前端·vue.js·架构
禁止摆烂_才浅17 小时前
Vue2 高频面试题
前端·vue.js·面试
禁止摆烂_才浅18 小时前
Vue3 高频面试题
前端·vue.js·面试
独立开阀者_FwtCoder18 小时前
这次更新:换新主题,同时把好计划分享出去
前端·javascript·vue.js
资源大佬星 课it1 天前
重学C++ ,重构你的C++知识体系
vue.js·docker·django