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)
    

3 自定义配置插件

  • Vue.use(VueLazyload,{
        // 设置相应的 loading 图和图片错误显示图
        error: require('@/assets/lazy/error.png'),
        loading: require('@/assets/lazy/loading.gif'),
        attempt: 1, // 尝试加载图片数量
        // try: 2 // 加载图片数量
    })
    

4 使用

  • 单图

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

    • <div v-lazy-container="{ selector: 'img' }">
        <img data-src="图片地址">
        <img data-src="图片地址">
        <img data-src="图片地址">
        <img data-src="图片地址">   
      </div>
      
  1. ❗✨注:
    • 背景图片中使用懒加载
      • v-lazy:background-image = '' 要注意图片和盒子大小问题
    • 使用时可以添加一个 key 属性

补充

属性 作用 默认值 类型
preLoad 预加载高度比例 1.3 Number
error 图片路径错误时加载图片 'data-src' String
loading 预加载图片(占位图片) 'data-src' String
attempt 尝试加载图片数量 3 Number

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

实现原理:

先储存图片地址 不能先放在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)
        },
    })
}
export default{
    install(Vue){
        defineDirective(Vue)
    }
}

基于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)
        },
    })
}
export default {
  install (app) {
    defineDirective(app)
  }
}

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

实现原理:

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

检测目标元素的可见性

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

技术方案:

我们可以使用 @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)通过 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>

3)测试效果

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

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

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

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

你可能感兴趣的:(前端性能优化,Vue,插件使用,vue.js,前端,javascript)