组件数据懒加载(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)

相关推荐

  • Python def

    Python defPython def 是 Python 语言中定义函数的关键字,它是编写高质量、可重用的代码的基础。在 Python 中,函数是一组语句,用于执行特定任务。使用 def 关键字定义函数后,可以在程序的其他地方调用该函数。

    2024-08-13
    24
  • MySQL完整版详解「终于解决」

    MySQL完整版详解「终于解决」一、数据库的操作 1.创建数据库 若在可视化软件上创建数据库,参考如下图 如果要创建的数据库不存在,则创建成功 create database if not exists westos; 2.删除数据

    2023-05-26
    148
  • 我被骗好久了!count(*) 性能最差?[通俗易懂]

    我被骗好久了!count(*) 性能最差?[通俗易懂]我曾经以为 count(`*`) 是效率最差的,因为认知上 `selete * from t` 会读取所有表中的字段,所以凡事带有 `*` 字符的就觉得会读取表中所有的字段,当时网上有很多博客也这么说

    2023-08-04
    113
  • 利用jinja2编写Python Web应用的基本方法

    利用jinja2编写Python Web应用的基本方法随着互联网技术的发展,越来越多的网站和应用程序被开发出来。其中,Web应用程序是最为流行的一种,Python作为一种优秀的编程语言被广泛地应用于Web应用程序的开发中。在Python的Web框架中,Jinja2是一种非常受欢迎、高效、灵活的模板引擎。下面将详细介绍利用Jinja2编写Python Web应用的基本方法。

    2024-05-12
    73
  • 【StoneDB研发日志】列式存储 delete方案调研

    【StoneDB研发日志】列式存储 delete方案调研MySQL删除数据的方式 以MySQL 5.7为例,数据库删除数据的方式一共有以下三种: delete truncate drop 以上三种方式都可以删除数据,但是使用场景是不同的。 对于整个表进行删

    2023-05-31
    150
  • Oracle RAC 各个版本ASM使用共享文件系统的需求[亲测有效]

    Oracle RAC 各个版本ASM使用共享文件系统的需求[亲测有效]ASM磁盘需求

    2023-04-04
    152
  • Taro 小程序开发大型实战(一):熟悉的 React,熟悉的 Hooks「终于解决」

    Taro 小程序开发大型实战(一):熟悉的 React,熟悉的 Hooks「终于解决」正当移动互联网进入白热化阶段时,以微信小程序为代表的一类“轻应用”异军突起。它们无需下载,使用方便,“用完即走”,同时功能也较为完备,一经推出即得到了各大平台和及用户的热烈追捧。但是问题也随之而来——开发者们要同时维护 Web 端、移动端、微信小程序、支付宝小程序等等多套用户界…

    2023-07-18
    118
  • MySQL篇「终于解决」

    MySQL篇「终于解决」2、Mysql 的技术特点是什么? Mysql 数据库软件是一个客户端或服务器系统,其中包括:支持各种客户端程序和库的多 线程 SQL 服务器、不同的后端、广泛的应用程序编程接口和管理工具。 3、He

    2023-03-07
    148

发表回复

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