Vue3 中实现组件数据懒加载

2,205 阅读2分钟

数据懒加载是一个不可避免要解决的事情 Vue3中又提供了什么方法来解决呢

使用 @vueuse/core 中的 useIntersectionObserver 来实现监听进入可视区域行为,配合vue3.0的组合API的方式实现。

  • 这是useIntersectionObserver 函数:
// const {stop} = useIntersectionObserver(target, fn, options)
// 1、参数一target表示被监听的DOM元素
// 2、参数二是回调函数,用于通知监听的动作(回调函数的第一个形参isIntersecting表示被监听的元素已经进入了可视区)
// 3、表示配置选项
// stop 是停止观察是否进入或移出可视区域的行为    
const { stop } = useIntersectionObserver(
  // target 是观察的目标dom容器,必须是dom容器,而且是vue3.0方式绑定的dom对象
  target,
  // isIntersecting 是否进入可视区域,true是进入 false是移出
  // observerElement 被观察的dom
  ([{ isIntersecting }], observerElement) => {
    // 在此处可根据isIntersecting来判断,然后做业务
  },
)

具体步骤

1.1这是具体的实现代码 可以封装成一个单独的文件 需要的时候直接导入

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

// 封装一个Hook方法实现数据懒加载
export const useLazyData = (apiFn) => {
  // 当前组件进入可视区时触发接口调用
  // 被监听的DOM元素
  const target = ref(null)
  // 调用接口获取的结果
  const result = ref([])
  const { stop } = useIntersectionObserver(target, ([{ isIntersecting }]) => {
    if (isIntersecting) {
      // 进入可视区
      apiFn().then(data => {
        result.value = data.result
      })
      // 停止监听
      stop()
    }
  })
  return { result, target }
}

2.需要的组件中直接使用

  • 哪个部分需要 加一个ref="target"

Snipaste_2021-09-15_19-28-18.png

  • 导入刚才的文件import { useLazyData } from '@/hook'
  • 直接使用

Snipaste_2021-09-15_19-32-11.png

2.1有一个小问题:

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

2.2原因:

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

2.2 解决:

补充一个参数:threshold ,容器和可视区交叉的占比(进入的面积/容器完整面积) 取值,直接取0

 const { stop } = useIntersectionObserver(
    target,
    ([{ isIntersecting }]) => {
      if (isIntersecting) {
        stop()
        apiFn()
      }
    },
    { threshold: 0}
  )
  return { result, target }
}