首页 > 其他分享 >vue3写一个触底加载hook

vue3写一个触底加载hook

时间:2024-08-27 11:53:58浏览次数:4  
标签:const value current hook vue3 isReachBottom elementRef 加载

天行健,地势坤 -- 《周易·象传》

背景:在一个滚动容器下实现触底加载更多的函数,由于此模块使用的场景较多,因而自己实现了一个滚动加载的hook(顺带尝试了下hook)

需求:左侧tab切换时,右侧聊天历史tab要清空并重新请求;右侧触底时,要触发分页请求(如果有);使用dayjs中的fromnow方法以精确体现用户在今日对话中的记录(略)。

  1. 基础知识引入

如何让一个容器触发滚动态:

一句话总结:容器的内容物高度大于容器本身高度且容器的css样式为overflow:auto时触发。

如何给一个容器添加滚动事件:

element.addEventListener('scroll', scrollFn)

  1. 代码实现

useBottomScroll.ts


import { nextTick, onMounted, onUnmounted, ref } from 'vue'

/**
 * elementRef : 传入的dom实例
 * onReachBottomFn :滚动加载函数
 * reachBottomDistance : 距离底部多少距离时触发
 */

function useScrollBottom(elementRef, onReachBottomFn, reachBottomDistance = 100) {
  const isReachBottom = ref(false)
  const onScroll = async () => {
    const scrollTop = elementRef.value.scrollTop
    const scrollHeight = elementRef.value.scrollHeight
    const clientHeight = elementRef.value.clientHeight
    const currentHeight = scrollTop + clientHeight
    const isAtBottom = currentHeight + reachBottomDistance >= scrollHeight
    if (isAtBottom && !isReachBottom.value) {
      // 调用传入的触底触发函数  bool 值代表是否还有更多数据
      const isEnd = await onReachBottomFn()
      isReachBottom.value = isEnd
    }
  }

  onMounted(async () => {
    nextTick(async () => {
      elementRef.value.addEventListener('scroll', onScroll)
      // 默认触发一次分页接口
      await onReachBottomFn()
    })
  })

  onUnmounted(() => {
    elementRef.value && elementRef.value.removeEventListener('scroll', onScroll)
  })

  return {
    isReachBottom
  }
}

export default useScrollBottom

这里最重要的有两点,

(1). 判断滚动的时机

滚动的时机以isAtBottom变量划定,即当前位置加上预设距离是否大于等于元素总高,如果是,则为true

(2). 修改滚动的条件:isReachBottom

修改滚动的条件isReachBottom则由调用方提供,本质上是当前页数current*当前条数size 是否大于等于 总条数total,每次在条件满足触发加载后都会重新赋值isReachBottom

  1. 业务调用:

<div ref="todayRef" class="scroll-container">
	<!--balabala-->
</div>

import useScrollBottom from '@/hooks/useBottomScroll.ts'

// 监听左侧tag页,一旦切换即重新触发
watch(
  () => currentTag.value,
  (n) => {
    todayBool.value = false
    todayList.value = []
    todayPage.value.current = 0
    loadMoreDataFn()
  },
  {
    immediate: true
  }
)

const todayList = ref([])
const todayRef = ref(null)
// 这里最重要的就是current  size默认写死,total可以扔掉
const todayPage = ref({ size: 10, current: 0, total: 0 } )
const { isReachBottom: todayBool } = useScrollBottom(todayRef, loadMoreDataFn)


const loadMoreDataFn= async () => {
  todayPage.value.current += 1
  const params = {
    current: todayPage.value.current,
    size: 10, 
  }
  const res = await getTodayStoryListApi(params)
  if (Array.isArray(res.records)) {
    todayList.value = [...todayList.value, ...res.records]
  }
 // 返回的isEnd参数-》params.current * params.size >= Number(res.total))
  return new Promise((c) => c(params.current * params.size >= Number(res.total)))
}
  1. 总结与分析

滚动加载最重要的其实就是current参数,不论tab页的切换亦或者触底后是否继续访问接口都与此息息相关,笔者原本准备将请求函数写在hook内部,但是如此一来就丧失了一些灵活性——固定输入,并且如果有时候在外部需要一些返回值时,又不方便提取(也可能是刚开始用hook),因而就将loadFn写在了外部,而触发的时机本质上有两个点:1,是否接近或者等于约定值,2. 外部传入的isEnd值是否为false,而isEnd又是外部传入的current*size >= total返回的布尔值,一套流程下来也就形成了闭环。

  1. 不足

之前仿照别的项目组时的做法,想在loadMoreDataFn内赋一个默认值isRefresh 来判断是否是否切换了左侧tab,但是测试后发现无效,猜测可能是在hook内部调用

const isEnd = await onReachBottomFn()
时没能将参数传递进去,这里百思不得其解,因而不得不在业务模块使用watch手动控制current和todayList的值,如有知道解决办法的也欢迎指教,不胜感激

以上。

标签:const,value,current,hook,vue3,isReachBottom,elementRef,加载
From: https://www.cnblogs.com/hjk1124/p/18382405

相关文章

  • 图片作为Canvas贴图时要等图片加载完才可以读取canvas
    一、效果二、第一步:canvas.js中封装canvas函数,生成一个canvas对象,标注文字为参数nameunctioncreateCanvas(name){  /**   *创建一个canvas对象,绘制几何图案或添加文字   */  constcanvas=document.createElement("canvas");  constarr=......
  • Vue3知识点
    1、ref和reactive的区别。① js中对ref定义的值读取、修改,需要加.value,可以用插件↓来简单使用   ② ref修改引用可以直接修改,react不能修改引用对象,只能使用Object.assign修改对象内容   ③ 基本类型建议使用ref,若需要一个响应式对象且层级不深ref和r......
  • 手把手教你—搭建Vue3企业级项目规范+基础封装配置
    前言如何搭建一个简易脚手架。核心需求是输入项目命令,clone准备好的项目模板,拉到本地后,装一下依赖,就可以直接开发了。不用每次都花大量时间,去搭建项目规范和做必要的封装配置。经过简单寻找后,发现没有符合自己预期的。从0到1搭建一个具备完善规范的Vue3开发模板✨,并手把手带大......
  • vue3uniapps使用富文本mp-html插件
    1.实现效果具体需求:顶部是搜索栏,包括搜索结果个数,目前跳到第几个,包含上一个、下一个按钮。富文本区域关键词高亮黄色,当前关键词为高亮橙色。如图2.版本号用到vue3和uniapp,mp-html插件版本是v2.5.0,插件地址:https://ext.dcloud.net.cn/plugin?id=805用npm方式打包放到......
  • Nginx加载Lua环境
    Nginx加载Lua环境开源配置也可以直接部署春哥的开源项⽬OpenResty:http://openresty.org/cn/#安装依赖包[root@linuxprobe]#yuminstall-yreadline-develpcre-developenssl-devel[root@linuxprobe]#cd/soft/src#下载并编译安装openresty[root@linuxprobesrc]#......
  • Vite+Vue3 项目 华仔待办
    此“华仔”,不是彼“华仔”,你懂的!先来了个截图紧跟着,实现步骤也来了1.安装Node.js,终端运行npmcreatevue@latest,项目名vue-to-do,后面的选项全选No;2.cdvue-to-do进入项目目录,npminstall安装依赖,npmrundev启动Vite开发服务器;3.修改index.html和main.js;i......
  • Vue3项目开发——新闻发布管理系统(三)
    文章目录七、登录&注册页面设计开发1、安装、导入`ElementPlus`组件库1.1安装1.2引用1.3设置中文1.4使用七、登录&注册页面设计开发网页页面设计肯定离不开表单、输入框、按钮等等控件的布局、样式等等的设计。在新闻发布管理系统中,使用ElementPlus......
  • [vue3] vue3 setup函数
    从语法上看,CompositionAPI提供了一个setup启动函数作为逻辑组织的入口,提供了响应式API,提供了生命周期函数以及依赖注入的接口,通过调用函数来声明一个组件。OptionsAPI选项式API在props、data、methods、computed等选项中定义变量;在组件初始化阶段,Vue.js内部处理这......
  • 使用Vue3实现响应式表单验证
    使用Vue3实现响应式表单验证在现代Web开发中,用户交互的体验一直是开发者关注的重点之一,其中,表单验证是提升用户体验的重要环节之一。借助Vue3的强大特性,我们可以轻松地实现一个响应式的表单验证系统。本文将逐步引导你如何使用Vue3的CompositionAPI(setup语法糖)来构建一......
  • Vue3 + Vue Router实现动态路由导航
    Vue3+VueRouter实现动态路由导航随着单页面应用程序(SPA)的日益流行,前端开发逐渐向复杂且交互性强的方向发展。在这个过程中,Vue.js及其生态圈的工具(如VueRouter)为我们提供了强大的支持。本文将介绍如何在Vue3中使用VueRouter实现动态路由导航,帮助你增强应用的灵活......