Vue3项目中如何实现数据懒加载

1.应用场景

如果访问的页面数据过多,为减少并发量,减少系统资源的消耗,这时候就需要用到懒加载,实现当组件进入可视区后再去发请求加载数据。

2.思路分析

如何判断一个dom元素是否进入了可见区域?

传统:获取dom位置 → getBoundingClientRect()

现在:直接判断元素进入可视区域的比例 → IntersectionObserver()

在本项目中,我们使用@vueuse/core中的 useIntersectionObserver()

3.使用

① 定义一个target,并导出,监测谁,就在谁身上通过ref调用。

② 引入 useIntersectionObserver 并使用

  • target 是观察的目标容器 dom对象 | 组件对象 
  • stop 是一个函数。如果调用它,就会停止观察(是否进入或移出可视区域的行为)
  • isIntersecting 是一个bool值,表示是否进入可视区域。 true表示 进入 false表示 移出
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
export default {
  setup () {
     const target = ref(null)
     const { stop } = useIntersectionObserver(target, ([{ isIntersecting }], observerDom) => {
       console.log('home-hot', isIntersecting, stop)
       // 如果target可见
       if (isIntersecting) {
         // 1.停止观察
         stop()
         // 2.发ajax
         findHot().then(data => {
           goods.value = data.result
         })
       }
     })

    return { target }
  }
}

4.封装通用逻辑

4.1 原因

在项目中,如果多个组件都需要用到懒加载,这时候每次都在组件中引入使用,会产生大量重复代码。

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

/**
 * 功能: 数据懒加载
 *
 * @param {*} fn  当目标可见时,要调用一次的函数
 * @returns target: 要观察的目标(vue3的引用)
 */
const useLazyData = (fn) => {
  const target = ref(null)
  const { stop } = useIntersectionObserver(
    target, // target 是vue的对象引用。是观察的目标
    // isIntersecting 是否进入可视区域,true是进入 false是移出
    // observerElement 被观察的dom
    ([{ isIntersecting }], observerElement) => {
      if (isIntersecting) { // 目标可见,
        // 1. ajax可以发了,后续不需要观察了
        stop()
        // 2. 执行函数
        fn()
      }
    }
  )

  return target
}

export default useLazyData

4.2 在组件中使用

import { findNew } from '@/api/home'
import useLazyData from '@/compositions'
export default {
  name: 'HomeNew',
  setup () {
    const fn = () => {
      findNew().then(data => {
        console.log('findNew', data)
        list.value = data.result
      })
    }
    const target = useLazyLoad(fn)

    return { target }
  }
}

5.一个不知道算不算bug的小问题

如果需要懒加载的组件面积比较大,页面需要滚动比较多的面积才回去加载数据,用户体验不好。

5.1 原因 

useIntersectionObserver 默认以进入视口的面积占总元素面积的0.1为基准判断是否进入,而这里的默认比例0.1在元素比较大的时候,会有这个问题:看起来已经可见了,但是我们回调没有执行。

5.2 解决

补充一个参数:threshold ,容器和可视区交叉的占比(进入的面积/容器完整面积) 取值,0-1 之间,默认是0.1,所以需要滚动较多才能触发进入可视区域事件。

  const { stop } = useIntersectionObserver(
    container,
    ([{ isIntersecting }], dom) => {
      if (isIntersecting) {
        stop()
        fn()
      }
+    }, {
+      threshold: 0
+    }
  )

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值