通过交叉实现数据触底分页效果new IntersectionObserver()(html、react、vue2、vue3)中使用

news2024/12/28 17:11:34

react中用法 

import React, { useState, useEffect, useRef } from 'react';

const InfiniteScroll = () => {
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(false);
  const [page, setPage] = useState(1);
  const loaderRef = useRef(null);

  // 模拟加载更多数据的函数
  const loadMoreData = () => {
    if (loading) return; // 防止重复加载
    setLoading(true);

    // 模拟异步数据请求
    setTimeout(() => {
      const newItems = Array.from({ length: 10 }, (_, index) => `Item ${(page - 1) * 10 + index + 1}`);
      setItems((prevItems) => [...prevItems, ...newItems]);
      setPage((prevPage) => prevPage + 1);
      setLoading(false);
    }, 1000); // 模拟请求延时
  };

  useEffect(() => {
    // 创建 IntersectionObserver
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          loadMoreData(); // 当加载元素进入视口时,触发加载更多数据
        }
      },
      {
        rootMargin: '0px', // 可根据需要调整,决定何时触发
        threshold: 1.0, // 触发条件:元素完全进入视口
      }
    );

    // 启动观察
    if (loaderRef.current) {
      observer.observe(loaderRef.current);
    }

    // 清理 observer
    return () => {
      if (loaderRef.current) {
        observer.unobserve(loaderRef.current);
      }
    };
  }, [loading, page]);

  return (
    <div>
      <div>
        {items.map((item, index) => (
          <div key={index}>{item}</div>
        ))}
      </div>
      {/* 触底加载元素 */}
      <div ref={loaderRef}>
        {loading ? <p>Loading...</p> : <p>Scroll down to load more...</p>}
      </div>
    </div>
  );
};

export default InfiniteScroll;

原生js中用法 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Infinite Scroll with IntersectionObserver</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            padding: 0;
            margin: 0;
            height: 2000px; /* Just to make the page scrollable */
        }
        .item {
            padding: 10px;
            margin: 10px 0;
            background-color: #f4f4f4;
            border: 1px solid #ddd;
        }
        #loading {
            text-align: center;
            padding: 10px;
            background-color: #f1f1f1;
        }
    </style>
</head>
<body>
    <div id="content">
        <!-- 初始内容 -->
        <div class="item">Item 1</div>
        <div class="item">Item 2</div>
        <div class="item">Item 3</div>
        <div class="item">Item 4</div>
        <div class="item">Item 5</div>
    </div>
    
    <!-- 加载更多的提示 -->
    <div id="loading">Loading more...</div>

    <script>
        // 模拟加载更多数据的函数
        let page = 1;
        const loadMoreData = () => {
            // 模拟异步请求数据
            setTimeout(() => {
                const content = document.getElementById('content');
                for (let i = 0; i < 5; i++) {
                    const newItem = document.createElement('div');
                    newItem.classList.add('item');
                    newItem.textContent = `Item ${page * 5 + i + 1}`;
                    content.appendChild(newItem);
                }
                page++;
            }, 1000); // 模拟1秒的延迟
        };

        // 设置 IntersectionObserver 监听“加载更多”元素
        const loadingElement = document.getElementById('loading');

        const observer = new IntersectionObserver((entries, observer) => {
            // 只在元素完全进入视口时触发
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    loadMoreData();
                    observer.unobserve(loadingElement); // 停止监听当前元素
                    observer.observe(loadingElement); // 重新开始监听
                }
            });
        }, {
            rootMargin: '0px',
            threshold: 1.0 // 完全进入视口时触发
        });

        // 启动 IntersectionObserver
        observer.observe(loadingElement);
    </script>
</body>
</html>

Vue2中使用

<template>
  <div>
    <!-- 内容部分 -->
    <div class="content">
      <div v-for="(item, index) in items" :key="index" class="item">
        {{ item }}
      </div>
    </div>

    <!-- 加载更多提示 -->
    <div id="loading" class="loading">加载更多...</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: ['Item 1', 'Item 2', 'Item 3'], // 初始数据
      page: 1, // 当前页数
    };
  },
  mounted() {
    // 设置 IntersectionObserver 监听加载更多区域
    const loadingElement = document.getElementById('loading');
    const observer = new IntersectionObserver(this.handleIntersection, {
      rootMargin: '0px',
      threshold: 1.0, // 完全进入视口时触发
    });
    observer.observe(loadingElement);
  },
  methods: {
    handleIntersection(entries, observer) {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          // 如果加载更多区域进入视口,加载更多数据
          this.loadMoreData();
        }
      });
    },
    loadMoreData() {
      setTimeout(() => {
        const newItems = Array.from({ length: 5 }, (_, i) => `Item ${this.page * 5 + i + 1}`);
        this.items.push(...newItems); // 添加新数据
        this.page += 1; // 增加页码
      }, 1000); // 模拟网络请求延时
    },
  },
};
</script>

<style>
.content {
  height: 1500px; /* 让页面滚动 */
}

.item {
  padding: 10px;
  margin: 10px 0;
  background-color: #f4f4f4;
  border: 1px solid #ddd;
}

.loading {
  text-align: center;
  padding: 10px;
  background-color: #f1f1f1;
}
</style>

Vue3中使用

<template>
  <div>
    <!-- 内容部分 -->
    <div class="content">
      <div v-for="(item, index) in items" :key="index" class="item">
        {{ item }}
      </div>
    </div>

    <!-- 加载更多提示 -->
    <div id="loading" class="loading">加载更多...</div>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const items = ref(['Item 1', 'Item 2', 'Item 3']); // 初始数据
    const page = ref(1); // 当前页数

    // 加载更多数据的函数
    const loadMoreData = () => {
      setTimeout(() => {
        const newItems = Array.from({ length: 5 }, (_, i) => `Item ${page.value * 5 + i + 1}`);
        items.value.push(...newItems); // 添加新数据
        page.value += 1; // 增加页码
      }, 1000); // 模拟网络请求延时
    };

    // 处理 IntersectionObserver 逻辑
    const handleIntersection = (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          loadMoreData(); // 如果加载更多区域进入视口,加载更多数据
        }
      });
    };

    // 在组件挂载时设置 IntersectionObserver
    onMounted(() => {
      const loadingElement = document.getElementById('loading');
      const observer = new IntersectionObserver(handleIntersection, {
        rootMargin: '0px',
        threshold: 1.0,
      });
      observer.observe(loadingElement);
    });

    return { items };
  },
};
</script>

<style>
.content {
  height: 1500px; /* 让页面滚动 */
}

.item {
  padding: 10px;
  margin: 10px 0;
  background-color: #f4f4f4;
  border: 1px solid #ddd;
}

.loading {
  text-align: center;
  padding: 10px;
  background-color: #f1f1f1;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2267027.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringCloudAlibaba升级手册-nacos问题记录

目录 一、前言 二、升级过程 1.问题 2.原因 3.出处 4.理论解决 5.测试环境问题 6.Spring Cloud Alibaba版本对比 7. Spring Cloud Alibaba适配组件版本对比 8.降低Spring Cloud版本 9.SpringCloud与SpringBoot兼容对比表 10.naocs-client版本对比 三、最终解决 一…

15、【OS】【Nuttx】OS裁剪,运行指定程序,周期打印当前任务

背景 接之前wiki【Nsh中运行第一个程序】https://blog.csdn.net/nobigdeal00/article/details/144728771 OS还是比较庞大&#xff0c;且上面搭载了Nsh&#xff08;Nuttx Shell&#xff09;&#xff0c;需要接入串口才能正常工作&#xff0c;一般调试的时候用&#xff0c;非调试…

C# 窗体应用程序嵌套web网页,基于谷歌浏览器内核(含源码)

有一个winform项目&#xff0c;需要借助一个web项目来显示&#xff0c;并且对web做一些操作,web页目是需要用谷歌内核&#xff0c;基于谷歌 Chromium项目的开源Web Browser控件来开发写了一个demo。 安装步骤 第一步&#xff1a;右键项目&#xff0c;点击 管理NuGet程序包 , 输…

通过远程控制软件实现企业高效协作

在这个信息技术迅猛发展的时代&#xff0c;远程办公已经成为一种趋势&#xff0c;而远程控制软件则是连接分散团队的重要工具。技术的革新不仅推动了远程控制软件的广泛应用&#xff0c;也为现代办公带来了高效的协作体验。本文将探讨远程控制软件的发展&#xff0c;并以RayLin…

赋能开发者 | 麒麟信安受邀参加2024开放原子开发者大会,以技术为引领,以人才创发展

12月20至21日&#xff0c;以“一切为了开发者”为主题的“2024开放原子开发者大会暨首届开源技术学术大会”在湖北武汉举办。本届大会由开放原子开源基金会、中国通信学会联合主办&#xff0c;旨在贯彻落实国家软件发展战略&#xff0c;加速培育壮大我国开源生态。工业和信息化…

每天40分玩转Django:Django国际化

Django国际化 一、今日学习内容概述 学习模块重要程度主要内容国际化基础⭐⭐⭐⭐⭐基本概念、配置设置字符串翻译⭐⭐⭐⭐⭐翻译标记、消息文件模板国际化⭐⭐⭐⭐模板标签、过滤器动态内容翻译⭐⭐⭐⭐模型字段、表单翻译 二、国际化基础配置 # settings.py# 启用国际化 …

Elasticsearch 国产化替代方案之一 Easysearch 的介绍与部署指南

一、前言 在国内数字化转型浪潮和 信创 大背景下&#xff0c;“替代进口”成为许多企业级应用所需要面对的重要课题&#xff0c;搜索领域也不例外。 Elasticsearch&#xff08;简称 ES&#xff09;作为一款业界领先的全文搜索和分析引擎&#xff0c;虽然功能强大&#xff0c;但…

Ubuntu 24.04.1 LTS 配置静态固定IP地址

查看网络配置信息 ip addr使用该命令查看网卡名字&#xff0c;一般是ens33或者ens32 修改配置文件 打开 /etc/netplan/下面的yaml配置文件 根据自己的需要配置 network:ethernets:ens33: # 配置的网卡的名称addresses: [192.168.23.140/24] # 配置的静态ip地址和掩码d…

Deep Deterministic Policy Gradient (DDPG)算法

代码 import torch import torch.nn as nn import torch.optim as optim import numpy as np import gym import random from collections import deque# 定义 Actor 网络 class Actor(nn.Module):def __init__(self, state_dim, action_dim, max_action):super(Actor, self).…

C++ OCR 文字识别

一.引言 文字识别&#xff0c;也称为光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;&#xff0c;是一种将不同形式的文档&#xff08;如扫描的纸质文档、PDF文件或数字相机拍摄的图片&#xff09;中的文字转换成可编辑和可搜索的数据的技术。随着技…

【解决报错】AttributeError: ‘NoneType‘ object has no attribute ‘group‘

学习爬虫时&#xff0c;遇到如下报错&#xff1a; 报错原因&#xff1a; 正则表达式的 search 或 finditer 方法没有找到任何匹配项&#xff0c;可能是换行符处理不当等。 解决方法如下&#xff1a; 在正则表达式末尾加上re.S即可&#xff0c;re.S是一个编译标志&#xff0c…

JVM实战—3.JVM垃圾回收的算法和全流程

大纲 1.JVM内存中的对象何时会被垃圾回收 2.JVM中的垃圾回收算法及各算法的优劣 3.新生代和老年代的垃圾回收算法 4.避免本应进入S区的对象直接升入老年代 5.Stop the World问题分析 6.JVM垃圾回收的原理核心流程 7.问题汇总 1.JVM内存中的对象何时会被垃圾回收 (1)什么…

基于SpringBoot在线音乐系统平台功能实现十八

一、前言介绍&#xff1a; 1.1 项目摘要 随着互联网技术的迅猛发展和普及&#xff0c;人们对音乐的获取和欣赏方式发生了巨大改变。传统的音乐播放方式&#xff0c;如CD、磁带或本地下载的音乐文件&#xff0c;已经不能满足用户日益增长的需求。用户更希望通过网络直接获取各…

RouYi-Vue框架,环境搭建以及使用

使用若以框架需要配置node.js&#xff0c;如果不了解可以去看node.js安装&#xff0c;uni-app的配置使用_uniapp使用nodejs类库-CSDN博客 安装若依 首先是去若以官网下载自己所需要的框架类型 RuoYi-Vue: &#x1f389; 基于SpringBoot&#xff0c;Spring Security&#xff…

XL系列433芯片、2.4G收发芯片 通讯对码说明

XL系列433芯片对码说明&#xff1a; 发射芯片 XL4456 通过数据脚接收高低电平然后经过调制将波形发出&#xff0c;而接收芯片 XL520 通过接收波形后进行解调&#xff0c;数据脚输出高低电平。至于具体的通信协议&#xff0c;需要用户自定义&#xff0c;一般而言&#xff0c;使…

蓝牙BLE开发——解决iOS设备获取MAC方式

解决iOS设备获取MAC方式 uniapp 解决 iOS 获取 MAC地址&#xff0c;在Android、iOS不同端中互通&#xff0c;根据MAC 地址处理相关的业务场景&#xff1b; 文章目录 解决iOS设备获取MAC方式监听寻找到新设备的事件BLE工具效果图APP监听设备返回数据解决方式ArrayBuffer转16进制…

期权懂|如何计算期权卖方平仓后的盈利?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 如何计算期权卖方平仓后的盈利&#xff1f; 期权卖方平仓后的盈利计算涉及多个因素&#xff0c;包括期权的交易价格、平仓价格以及权利金的变动等。 交易价格&#xff1a;期权卖…

QT:一个TCP客户端自动连接的测试模型

版本 1:没有取消按钮 测试效果&#xff1a; 缺陷&#xff1a; 无法手动停止 测试代码 CMakeLists.txt cmake_minimum_required(VERSION 3.19) project(AutoConnect LANGUAGES CXX)find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets Network)qt_standard_project_setup(…

uniapp中wx.getFuzzyLocation报错如何解决

一、用wx.getLocation接口审核不通过 用uniapp开发小程序时难免需要获取当前地理位置。 代码如下&#xff1a; uni.getLocation({type: wgs84,success: function (res) {console.log(当前位置的经度&#xff1a; res.longitude);console.log(当前位置的纬度&#xff1a; r…

解决Ubuntu下无法装载 Windows D盘的问题

电脑安装了 Windows 和 Ubuntu 24.04 后&#xff0c;在Ubuntu系统上装载 D盘&#xff0c;发现无法装载错误如下&#xff1a; Error mounting /dev/nvme0n1p4 at /media/jackeysong/Data: wrong fs type, bad option, bad superblock on /dev/nvme0n1p4, missing codepage or h…