组件数据懒加载(vue3)

组件数据懒加载(vue3)1、何为组件数据懒加载? 前言 电商项目核心优化技术手段:组件数据懒加载 (首屏渲染优化) 电商类网站,首页内容有好几屏,如果一上来就加载所有屏的数据,并渲染所有屏的内容,必然发送很多次无效的请求,我

1、何为组件数据懒加载?

前言

电商项目核心优化技术手段:组件数据懒加载 (首屏渲染优化)

电商类网站,首页内容有好几屏,如果一上来就加载所有屏的数据,并渲染所有屏的内容,必然发送很多次无效的请求,我们应该等所在模块进入到 可视区 再发请求获取数据。

思考

  • 我们一般的数据请求在哪里发起? setup (created)
  • 生命周期钩子函数的特点是什么? 一加载组件,就立刻执行

结论

我们希望组件正式进入到 可视区 中时,才把组件内部的 ajax 请求发起,否则不请求数据,那如何判断进入可视区,并进行组件数据懒加载呢?

2、如何判断组件进入可视区?

技术方案

我们可以使用 @vueuse/core 中的 useIntersectionObserver来实现监听组件进入可视区域行为, 需要配合 vue3.0 的组合 API的方式才能实现

分析useIntersectionObserver 函数:

// 下包 npm i @vueuse/core@5.3.0 或 yarn add @vueuse/core@5.3.0
// 导入 useIntersectionObserver 函数
import { useIntersectionObserver } from '@vueuse/core'
// 1.stop 一个可执行的函数用来停止监听行为
// 2.target 一个由 ref api 调用之后形成的 RefImpl 对象 也可以是一个 dom 对象
// 3.isIntersecting 一个类型为布尔值的数据 当被监听元素进入视口区域时为 true ,离开视口区域时为 false
// 4.observerElement 被观察的dom
const { stop } = useIntersectionObserver(
  target,
  ([{ isIntersecting }], observerElement) => {
    targetIsVisible.value = isIntersecting
  }
)
// ◆特别注意: 对于目标target是否进入视口区域的监听会一直进行不会只监听一次,可以 stop() 关闭监听

3、实现组件数据懒加载(代码落地)

  1. 通过 ref 属性获得组件实例并测试
  2. 使用 useIntersectionObserver 监听函数
  3. 发送的ajax请求在 isIntersectingtrue 时触发
  4. 一旦触发一次之后停止监听 stop(),防止接口重复调用
<template>
  <HomePanel ref="target" title="人气推荐" sub-title="人气爆款 不容错过"> <ul class="goods-list"> <li v-for="item in hotList" :key="item.id"> <RouterLink to="/"> <img :src="item.picture" alt=""> <p class="name">{{item.title}}</p> <p class="desc">{{item.alt}}</p> </RouterLink> </li> </ul> </HomePanel> </template>

<script> // 导入子组件 HomePanel  import HomePanel from './home-panel' // 导入获取数据的件接口函数 import { reqFindHot } from '@/api/home' // 导入 ref 函数(使目标数据变成响应式数据) import { ref } from 'vue' // 导入 useIntersectionObserver 进行监听 import { useIntersectionObserver } from '@vueuse/core' export default { name: 'HomeHot', components: { HomePanel },// 注册子组件 setup () { const hotList = ref([]) const getHotList = async () => { const res = await reqFindHot() hotList.value = res.result } // getHotList() // 1.通过 ref 获得组件实例 const target = ref(null) // 2.使用 useIntersectionObserver 监听函数 const { stop } = useIntersectionObserver( target,// 3.target 是被观察的目标dom容器 ([{ isIntersecting }], observerElement) => { // 4.在此处可根据 isIntersecting 来判断,然后做处理 console.log(isIntersecting) // 5.如果 isIntersecting 为 true  if (isIntersecting) { stop()// 6.中止监听 getHotList()// 7.调用函数(发送请求) } } ) // 8.把 target 返回 return { hotList, target} } } </script>

4、组件数据懒加载的逻辑复用

事实上,首页中有很多地方都应该使用 组件数据懒加载 这个功能,不管是哪个模块使用,下面代码都会重复书写,可能会随着业务使用发生变化的是 ajax 接口的调用,其余的部分我们进行重复使用,抽离为可复用逻辑。

下面,我们将以上代码抽离出来进行复用:

新建 src/compositions/index.js

// ◆封装组件懒加载的函数
import { ref } from 'vue'
import { useIntersectionObserver } from '@vueuse/core'
// 按需导出
export function useObserver (apiFn) {// apiFn 为形参
  const target = ref(null)
  const { stop } = useIntersectionObserver(
    target,
    ([{ isIntersecting }], observerElement) => {
      console.log(isIntersecting, '666')
      if (isIntersecting) {
        stop()// 终止监听
        apiFn && apiFn()
      }
    }
  )
  return target// 一定要 return 出去
}

在需要的页面调用

<template>
  <HomePanel ref="target" title="人气推荐" sub-title="人气爆款 不容错过"> <ul class="goods-list"> <li v-for="item in hotList" :key="item.id"> <RouterLink to="/"> <img :src="item.picture" alt=""> <p class="name">{{item.title}}</p> <p class="desc">{{item.alt}}</p> </RouterLink> </li> </ul> </HomePanel> </template>

<script> import HomePanel from './home-panel' import { reqFindHot } from '@/api/home' import { ref } from 'vue' // import { useIntersectionObserver } from '@vueuse/core' // 1.按需导入封装好的组件懒加载函数 import { useObserver } from '@/compositions' export default { name: 'HomeHot', components: { HomePanel }, setup () { const hotList = ref([]) const getHotList = async () => { const res = await reqFindHot() hotList.value = res.result } // 2.调用封装好的函数,传实参过去 const target = useObserver(getHotList) // getHotList() return { hotList, target } } } </script>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13351.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注