数据懒加载以及图片懒加载(Vue项目)

3,075 阅读2分钟

前言

当一个单页面应用加载发送的请求很多时,页面可能会出来的很慢影响用户体验,此时我们就可以对项目进行优化,使用数据懒加载以及图片懒加载优化网络性能。懒加载的原理是当组件对象或者Dom对象出现在可视区域的时候再发送请求,这样可以大大减轻网络压力使得页面加载更快。

数据懒加载

首先介绍数据懒加载的实现方式,这里的数据、图片懒加载均使用到了第三方包@vueuse/core,这是一个功能非常强大的第三方包。以在Vue3项目中的实现举例:

安装@vueuse/core

yarn add @vueuse/core

在组件中引入ref函数以及@vueuse/core中的useIntersectionObserver

import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'

给组件对象或Dom对象添加ref属性

<demo ref='target'><demo>

在setup函数中使用

  setup () {
    // 通过ref函数获取组件对象
    const target = ref(null)
    // 定义数据加载函数
    const loadFn = () => {
      '进行获取操作'
    }
    // stop是停止监听的方法
    const { stop } = useIntersectionObserver(
      // target表示通过ref获取到的组件对象或Dom对象
      target,
      ([{ isIntersecting }], observerElement) => {
        // isIntersecting 代表组件对象是否进入可视区域
        if (isIntersecting) {
          // 进入可视区域后
          loadFn()
          // 停止监听 不然会一直监听
          stop()
        }
      }
    )
    return {
      target
    }
  }

抽离到js文件中以便复用

import { useIntersectionObserver } from '@vueuse/core'

/**
 * @description: 数据获取懒加载
 * @param: 组件对象或者Dom对象,获取数据的函数
 * @return:
 */
export function lazyLoad (target, loadFn) {
  const { stop } = useIntersectionObserver(
    target,
    ([{ isIntersecting }], observerElement) => {
      // isIntersecting 代表组件对象是否进入可视区域
      if (isIntersecting) {
        loadFn()
        // 停止监听 不然会一直监听
        stop()
      }
    }
  )
}

图片懒加载

当一个页面有非常多的图片时,img标签的src属性会向服务器发送大量请求获取图片资源此时就会造成比较大的网络压力。图片懒加载的原理是当图片进入可视区域时再给img标签的src属性赋值。此处使用用到了自定义指令配合Vue.use()进行注册。

在src中创建directive/index.js

import { useIntersectionObserver } from '@vueuse/core'
import defaultImg from '默认图片路径'

export default {
  install (Vue) {
    Vue.directive('imgLazy', {
      // Vue3自定义指令的钩子函数有所变化
      mounted (el, binding) {
        // el 元素  binding:通过binding.value可以取出传来的值
        const { stop } = useIntersectionObserver(
          el,
          ([{ isIntersecting }], observerElement) => {
            if (isIntersecting) {
              // 进入可视区域后给src属性赋值
              // 此处可以将图片请求错误一并处理
              el.onerror = () => {
                el.src = defaultImg
              }
              el.src = binding.value
              // 停止监听
              stop()
            }
          }
        )
      }
    })
  }
}

在main.js中进行注册

import { createApp } from 'vue'
import App from './App.vue'
import directPlugin from './directives'

createApp(App).use(directPlugin).mount('#app')