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>
相关推荐
一枚小小程序员哈1 小时前
基于Vue + Node能源采购系统的设计与实现/基于express的能源管理系统#node.js
vue.js·node.js·express
一枚小小程序员哈6 小时前
基于Vue的个人博客网站的设计与实现/基于node.js的博客系统的设计与实现#express框架、vscode
vue.js·node.js·express
定栓6 小时前
vue3入门-v-model、ref和reactive讲解
前端·javascript·vue.js
LIUENG7 小时前
Vue3 响应式原理
前端·vue.js
wycode8 小时前
Vue2实践(3)之用component做一个动态表单(二)
前端·javascript·vue.js
wycode9 小时前
Vue2实践(2)之用component做一个动态表单(一)
前端·javascript·vue.js
第七种黄昏9 小时前
Vue3 中的 ref、模板引用和 defineExpose 详解
前端·javascript·vue.js
pepedd86410 小时前
还在开发vue2老项目吗?本文带你梳理vue版本区别
前端·vue.js·trae
前端缘梦10 小时前
深入理解 Vue 中的虚拟 DOM:原理与实战价值
前端·vue.js·面试
HWL567910 小时前
pnpm(Performant npm)的安装
前端·vue.js·npm·node.js