• Vue项目性能优化之---自定义指令实现图片懒加载、首屏渲染优化(组件数据懒加载)、vue-lazyload的使用


    Vue项目性能优化之—自定义指令实现图片懒加载、首屏渲染优化(组件数据懒加载)、vue-lazyload的使用

    vue-lazyload实现图片懒加载

    1 安装 vue-lazyload
    • npm i vue-lazyload -S
    2 在 main.js 中进行引用
    • import VueLazyload from "vue-lazyload";
      Vue.use(VueLazyload)
      
      • 1
      • 2
    3 自定义配置插件
    • Vue.use(VueLazyload,{
          // 设置相应的 loading 图和图片错误显示图
          error: require('@/assets/lazy/error.png'),
          loading: require('@/assets/lazy/loading.gif'),
          attempt: 1, // 尝试加载图片数量
          // try: 2 // 加载图片数量
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    4 使用
    • 单图

      • <img  v-lazy ='图片地址' :key='图片地址'>
        
        • 1
    • 多图

      • <div v-lazy-container="{ selector: 'img' }">
          <img data-src="图片地址">
          <img data-src="图片地址">
          <img data-src="图片地址">
          <img data-src="图片地址">   
        </div>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
    1. ❗✨注:
      • 背景图片中使用懒加载
        • v-lazy:background-image = '' 要注意图片和盒子大小问题
      • 使用时可以添加一个 key 属性
    补充
    属性作用默认值类型
    preLoad预加载高度比例1.3Number
    error图片路径错误时加载图片'data-src'String
    loading预加载图片(占位图片)'data-src'String
    attempt尝试加载图片数量3Number

    自定义指令实现图片懒加载

    实现原理:

    先储存图片地址 不能先放在src上(放在src上直接发请求了) 当图片进入可视区 将src地址换成存储地址

    IntersectionObserver介绍

    • callback
      • 两个回调参数 entries , observer
        • entries
          • 被观察的元素信息对象的数组 [{元素信息},{}],信息中的isIntersecting用来判断进入或离开
        • observer
          • 观察实例
    • options 配置参数
      • root
        • 基于的滚动容器,默认是document
      • rootMargin
        • 容器有没有外边距
      • threshold
        • 交叉的比例
    • 实例提供的两个方法
      • observe(dom)
        • 观察哪个dom
      • unobserve(dom)
        • 停止观察那个dom

    实现步骤

    1. app.directive() 传入自定义指令的名称和配置

    2. 当使用指令的DOM创建好后,创建一个观察对象 来观察当前使用指令的元素并开始观察

    3. 当进入可视区后停止观察

    4. 把指令的值设置给 el 的 src 属性 ( binding.value 就是指令的值 )

    5. 处理图片加载失败 error是图片加载失败的事件 加载失败后设置默认图 load是图片加载成功

    代码实现

    基于vue2.0和 IntersectionObserver封装懒加载指令
    // 图片地址(可通过
    import defaultImg from '@/assets/images/200.png'
    // 定义指令
    const defineDirective = (Vue) => {
        // 1.图片懒加载 v-lazy  指令directive
        Vue.directive('lazy', {
            // 监听使用指令的DOM是否创建好
            // el -->传入的dom   binding  --->传入的图片路径
            inserted(el,binding) {  
                // 2.创建一个观察对象 来观察当前使用指令的元素
                const observe = new IntersectionObserver(([{isIntersecting}]) => {
                    if (isIntersecting) {
                        // 进入可视区
                        // 停止观察
                        observe.unobserve(el)
                        // 3.把指令的值设置给el的src属性  binding.value 就是指令的值
                        // 4.处理图片加载失败  error是图片加载失败的事件  load是图片加载成功
                        el.onerror = () => {
                            // 加载失败 设置默认图
                            el.src = defaultImg
                        }
                        el.src = binding.value
                    }
                 }, {
                    threshold:0.01
                })
                // 开启观察
                observe.observe(el)
            },
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    export default{
        install(Vue){
            defineDirective(Vue)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    基于vue3.0和 IntersectionObserver封装懒加载指令
    import defaultImg from '@/assets/images/200.png'
    // 定义指令
    const defineDirective = (app) => {
        // 1.图片懒加载 v-lazy  指令directive
        // 原理:先储存图片地址 不能先放在src上(放在src上直接发请求了) 当图片进入可视区 将src地址换成存储地址
        app.directive('lazy', {
            // 监听使用指令的DOM是否创建好
            // el -->传入的dom   binding  --->传入的图片路径
            mounted(el,binding) {  
                // 2.创建一个观察对象 来观察当前使用指令的元素
                const observe = new IntersectionObserver(([{isIntersecting}]) => {
                    if (isIntersecting) {
                        // 进入可视区
                        // 停止观察
                        observe.unobserve(el)
                        // 3.把指令的值设置给el的src属性  binding.value 就是指令的值
                        // 4.处理图片加载失败  error是图片加载失败的事件  load是图片加载成功
                        el.onerror = () => {
                            // 加载失败 设置默认图
                            el.src = defaultImg
                        }
                        el.src = binding.value
                    }
                 }, {
                    threshold:0.01
                })
                // 开启观察
                observe.observe(el)
            },
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    export default {
      install (app) {
        defineDirective(app)
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    首屏渲染优化(组件数据懒加载)

    实现原理:

    当模块进入到 可视区 ,再发请求获取数据

    检测目标元素的可见性

    任务目标: 了解如何检测目标元素的可见性

    技术方案:

    我们可以使用 @vueuse/core 中的 useIntersectionObserver 来实现监听组件进入可视区域行为,需要配合 vue3 的组合 API 的方式才能实现

    先分析下这个useIntersectionObserver 函数

    🔔核心单词解释

    • useIntersectionObserver 检查元素是否进入可视区函数
    • target 目标元素,🎯需配合模板 ref 使用
    • isIntersecting 是否进入可视区(布尔值)
    • stop 用于停止检测的函数
    <script setup lang="ts">
    import { ref } from 'vue';
    import { useIntersectionObserver } from '@vueuse/core';
    
    // 准备目标元素(DOM节点或组件,需配合模板 ref 使用)
    const target = ref(null);
    
    const { stop } = useIntersectionObserver(target, ([{ isIntersecting }]) => {
      console.log('检测元素可见性', isIntersecting);
      // 需求:如果目标元素进入可视区,就发送请求,并停止检测
      if (isIntersecting) {
        // 当目标元素进入可视区域时,才发送请求
        console.log('进入可视区,需要发送请求');
        // 请求已发送,主动停止检查
        stop();
      }
    });
    </script>
    
    <template>
      <div style="height: 2000px"></div>
      <!-- 🎯目标元素需添加模板 ref  -->
      <div ref="target">
        <h1>🎯我是目标元素🎯</h1>
      </div>
      <div style="height: 2000px"></div>
    </template>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    我们以新鲜好物模块为例演示一下这个函数的使用方式

    1)通过 ref 属性获得组件实例并测试

    2)使用useIntersectionObserver监听函数

    <script setup lang="ts">
    import HomePanel from "./home-panel.vue";
    import { ref } from "vue";
    import { useIntersectionObserver } from "@vueuse/core";
    import useStore from "@/store";
    const { home } = useStore();
    // 通过 ref 获得组件实例
    const target = ref(null);
    const { stop } = useIntersectionObserver(
      // target 被检测的目标元素
      target,
      // isIntersecting 是否进入可视区域
      ([{ isIntersecting }]) => {
        // 在此处可根据isIntersecting来判断,然后做业务
        console.log('是否进入可视区域', isIntersecting);
        if (isIntersecting) {
          home.getHotGoodsList();
          stop();
        }
      }
    );
    script>
    
    <template>
      <div class="home-hot">
        
        <HomePanel ref="target" title="人气推荐" sub-title="人气爆款 不容错过">
          ...
        HomePanel>
      div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3)测试效果

    打开浏览器,人气推荐模块还未进入到可视区,打印值为false,

    然后我们滑动页面,当人气模块组件进入可视区中时,再次发生打印,此时为true,

    到此我们就可以判断组件进入和离开可视区了

    特别注意:每次被监听的dom进入离开可视区时都会触发一次,而不是只触发一次, 可以stop关闭监听

  • 相关阅读:
    MySQL学习笔记--innodb锁机制
    使用[阿里问题定位神器]Arthas入门
    Java项目:ssm教材征订与发放管理系统
    【虚幻引擎】UE4/UE5 后期处理盒子(PostProcessVolume)
    IIC学习笔记(参考小梅哥教程)
    计算机的基本组成
    多元联合分布建模 Copula python实例
    SpringMVC
    VMware虚拟机安装+Ubuntu安装+VMware Tools安装+虚拟机中系统的移动
    C语言趣味代码(一)
  • 原文地址:https://blog.csdn.net/weixin_43323097/article/details/126599209