DAMO开发者矩阵 前端react&vue3——实现滚动到底加载数据

前端react&vue3——实现滚动到底加载数据

文章目录⭐前言⭐react 实现滚动加载⭐vue3 实现滚动加载⭐总结⭐结束⭐前言大家好,我是yma16,本文分享 前端react&vue3——实现滚动加载(到底部加载)scrollTop 属性一个双精度浮点值,表示元素当前从原点垂直滚动的像素数,其中正值表示元素向下滚动(以显示更多底部的内容)。如果元素根本没有向...

egzosn  ·  2024-10-28 17:00:03 发布
文章目录
  • ⭐前言
  • ⭐react 实现滚动加载
  • ⭐vue3 实现滚动加载
  • ⭐总结
  • ⭐结束

⭐前言

大家好,我是yma16,本文分享 前端react&vue3——实现滚动加载(到底部加载)scrollTop 属性

一个双精度浮点值,表示元素当前从原点垂直滚动的像素数,其中正值表示元素向下滚动(以显示更多底部的内容)。如果元素根本没有向上或向下滚动,则 scrollTop 为 0。如果文档不是活动文档,则返回值为 0。如果文档在亚像素精度设备上呈现,则返回的值也是亚像素精度的,可能包含小数部分。

clientHeight 属性

只读属性 Element.clientHeight 对于没有定义 CSS 或者内联布局盒子的元素为 0;否则,它是元素内部的高度(以像素为单位),包含内边距,但不包括边框、外边距和水平滚动条(如果存在)。
clientHeight 可以通过 CSS height + CSS padding - 水平滚动条高度(如果存在)来计算。

scrollHeight 属性

scrollHeight 只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容

⭐react 实现滚动加载

判断滚动到底部:Math.ceil(scrollTop+clientHeight+1)>= scrollHeight 这里+1和向上取整是考虑到scrollTop是浮点数
react demo 案例:

import { useEffect, useRef, useState, useCallback } from 'react';
import {Button,notification} from 'tdesign-react'

const ScrollDemo=(props:any,ref:any)=> {
  // @ts-ignore 列表数据
  const [listData,setListData]=useState<any>([])
  // ref
  const scrollRef=useRef<HTMLElement|any>(null);
  // 初始化数据
  const initData=()=>{
    const data=[];
    for(let i=1;i<50;++i){
      data.push({
        label:`label${i}`,
        value:`label${i}`,
      })
    }
    return data
  };
  // 重置
  const resetData=()=>{
    setListData(initData())
  };

  //追加数据
  const appendData=useCallback(()=>{
    const data=[];
    const length=listData.length
    for(let i=length+1;i<10+length;++i){
      data.push({
        label:`label${i}`,
        value:`label${i}`,
      })
    }
    setListData(listData.concat(data))
  },[listData])
  //滚动事件
  const scrollEvent=(e:any)=>{
    console.log('e',e)
    // 不使用滚动条的情况下为了适应视口中所用内容所需的最小高度
    const scrollHeight=e.target.scrollHeight
    // 从其顶部边缘滚动的像素数
    const scrollTop=e.target.scrollTop
    // dom 视口高度(不包含任何滚动条)
    const clientHeight=e.target.clientHeight
    console.log('scrollTop',scrollTop)
    console.log('clientHeight',clientHeight)
    console.log('scrollHeight',scrollHeight)
    // 向上取整
    if(Math.ceil(scrollTop+clientHeight+1)>= scrollHeight ){
      notification.info({
        title: '到底啦!',
      })
      appendData()
    }
  }
  //监听 dom滚动
  const listenDomScroll=()=>{
    try{
      if(scrollRef.current){
        //@ts-ignore
        scrollRef.current.removeEventListener('scroll',scrollEvent)
        scrollRef.current.addEventListener('scroll',scrollEvent)
      }
    }
    catch (e) {
      console.error(e)
    }
  };

  //  初始化
  useEffect(()=>{
    resetData()
  },[])
  // 数据变化重新监听dom
  useEffect(()=>{
    if(scrollRef.current){
      listenDomScroll()
    }
  },[scrollRef,listData])
  return <div style={{padding:'10px',textAlign:'left'}}>
<Button onClick={resetData} style={{margin:'10px'}}>
  重置
</Button>

    <div>
      <div style={{maxHeight:'300px',width:'200px',overflowY:'auto',}} ref={scrollRef}>
        {listData.map((item:any)=>{
          return <div key={item.value} style={{background:'#0052d9',color:'#fff',margin:'2px',padding:'2px'}}>{item.label}</div>
        })}
      </div>
    </div>

    </div>
};
export default ScrollDemo

效果:

前端react&vue3——实现滚动到底加载数据_Data

⭐vue3 实现滚动加载

vue3 demo 实例:

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { notification } from 'ant-design-vue'
const scrollRef = ref()
type ListDataType = { label: string, value: string }
// 初始化数据
const initData = (): ListDataType[] => {
    const data: ListDataType[] = [];
    for (let i = 1; i < 50; ++i) {
        data.push({
            label: `label${i}`,
            value: `label${i}`,
        })
    }
    return data
};
// state 
const state: any = reactive({
    listData: initData()
})

// 重置
const resetData = () => {
    state.listData = initData()
};

//追加数据
const appendData = () => {
    const data: any = [];
    const length = state.listData.length
    for (let i = length + 1; i < 10 + length; ++i) {
        data.push({
            label: `label${i}`,
            value: `label${i}`,
        })
    }
    state.listData = [...state.listData, ...data]
}
//滚动事件
const scrollEvent = (e: any) => {
    console.log('e', e)
    // 不使用滚动条的情况下为了适应视口中所用内容所需的最小高度
    const scrollHeight = e.target.scrollHeight
    // 从其顶部边缘滚动的像素数
    const scrollTop = e.target.scrollTop
    // dom 视口高度(不包含任何滚动条)
    const clientHeight = e.target.clientHeight
    console.log('scrollTop', scrollTop)
    console.log('clientHeight', clientHeight)
    console.log('scrollHeight', scrollHeight)
    // 向上取整
    if (Math.ceil(scrollTop + clientHeight + 1) >= scrollHeight) {
        notification.open({
            message: '到底啦!',
        })
        appendData()
    }
}
//监听 dom滚动
const listenDomScroll = () => {
    try {
        if (scrollRef.value) {
            //@ts-ignore
            scrollRef.value.removeEventListener('scroll', scrollEvent)
            scrollRef.value.addEventListener('scroll', scrollEvent)
        }
    }
    catch (e) {
        console.error(e)
    }
};


// 初始化页面
onMounted(() => {
    listenDomScroll()
})

</script>
<template>
    <div>
        <a-button type="primary" @click="resetData">重置</a-button>
        <div style="max-height:300px;overflow-y:auto;width:200px" ref="scrollRef">
            <div v-for="item in state.listData" :key="item.value"
                style="background:#0052d9;color:#fff;padding:2px;margin:2px;">
                {{ item.label }}
            </div>
        </div>
    </div>
</template>

效果:

前端react&vue3——实现滚动到底加载数据_react.js_02

代码块inscode

⭐总结

底部加载的关键判断条件是:Math.ceil(scrollTop + clientHeight + 1) >= scrollHeight。

在使用react时,需要注意通过dom监听数据的变化。而在使用vue3时,数据具有响应式特性,因此只需在滚动加载时添加数据即可。

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!

前端react&vue3——实现滚动到底加载数据_前端框架_03

👍 点赞,是我创作的动力!

⭐️ 收藏,是我努力的方向!

✏️ 评论,是我进步的财富!

💖 最后,感谢你的阅读!

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐

  • 浏览量 727
  • 收藏 0
  • 0

所有评论(0)

查看更多评论 
已为社区贡献13条内容