数据懒加载和图片懒加载

数据懒加载是项目优化的一种类型

主要是监听, 监听的 DOM 元素是否有进入可视区

进入了可视区就可以做一些事情, 如: 发送请求, 返回出数据

离开可视区停止对 DOM 元素的监听

首先我们使用的是和 Vue3 配套的一个工具提供的一个方法

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

/**
* 数据懒加载函数
* @param {Function} apiFn - api函数
*
**/
export const useLazyData = (apiFn) => {
  // 初始化一个目标对象
  const target = ref(null)
  const result = ref([])

  // 这个函数调用的返回值是一个对象, 此对象中有一个成员stop函数
  // 它使用用来停止监听的函数

  // 此函数的第一个参数是监听的DOM对象
  // 第二个参数是一个回调函数
  const { stop } = useIntersectionObserver(
    target,

    // isIntersecting它是一个布尔值, 如果监听对象进入了可视区; 值为true, 否则为false
    // observerElement就是观察的元素
    ([{ isIntersecting }], observerElement) => {
      if (isIntersecting) {
        stop()
        apiFn().then(data => {
          result.value = data.result
        })
      }
    },
    
    // 第三个参数是交叉比例
    {
      threshold: 0
    }
  )

  return { target, result }
}
const { target, result } = useLazyData(findHot)

上面做数据懒加载的效果是使用的别人封装好的方法来进行实现的

那么现实我们实现图片懒加载的效果, 我们就自己手写原生来实现吧

我们主要使用到的API是 IntersectionObserver

// 创建观察对象实例
const observer = new IntersectionObserver(callback[, options])
// callback 被观察dom进入可视区离开可视区都会触发
// - 两个回调参数 entries , observer
// - entries 被观察的元素信息对象的数组 [{元素信息},{}],信息中isIntersecting判断进入或离开
// - observer 就是观察实例
// options 配置参数
// - 三个配置属性 root rootMargin threshold
// - root 基于的滚动容器,默认是document
// - rootMargin 容器有没有外边距
// - threshold 交叉的比例

// 实例提供两个方法
// observe(dom) 观察哪个dom
// unobserve(dom) 停止观察那个dom

图片懒加载的原理就是, 使用自定义指令去控制监听的 img 标签的 src 的值

当 img 标签的 src 没有值的时候是不会发送请求的, 所以我们可以通过这一点来完成需求

思路分析:

1. 首先我们需要定义一个自定时指令(directive)

2. Vue3 中和 Vue2 中自定义指令的定义有所不同, Vue3 组件的实例是 app; Vue2 组件实例是vue

3. 且 Vue2 中使用的方法是 inserted, Vue3 中使用的是 mounted

4. 通过 mouted 方法获取到 el 和 binding 两个参数, 动态的修改 el.src 的值即可

import XtxSkeleton from './xtx-skeleton.vue'
import XtxCarousel from './xtx-carousel.vue'
import XtxMore from './xtx-more.vue'

import defaultImg from '@/assets/images/200.png'

export default {
  install (app) {
    app.component('XtxSkeleton', XtxSkeleton)
    app.component('XtxCarousel', XtxCarousel)
    app.component('XtxMore', XtxMore)

    // 图片懒加载自定义指令
    defineDirective(app)
  }
}

const defineDirective = (app) => {
  // 自定义指令第一个参数是, 自定义指令名称
  // 第二个参数是, 自定义指令的配置项
  app.directive('lazy', {
    // el是添加自定义指令的DOM元素
    // binding接收到自定义指令传入的值
    mounted (el, binding) {
      const observer = new IntersectionObserver(([{ isIntersecting }]) => {
        if (isIntersecting) {
          observer.unobserve(el)
          // 当DOM元素加载失败时, 走的回调函数
          el.onerror = () => {
            el.src = defaultImg
          }
          el.src = binding.value
        }
      }, {
        threshold: 0
      })
      observer.observe(el)
    }
  })
}
/* 这里就不用添加src属性了, 因为自定义指令内部已经处理了 */
<img v-lazy="item.picture" alt="">

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值