通过交叉实现数据触底分页效果new IntersectionObserver()(html、react ...

打印 上一主题 下一主题

主题 1705|帖子 1705|积分 5115

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
react中用法 

  1. import React, { useState, useEffect, useRef } from 'react';
  2. const InfiniteScroll = () => {
  3.   const [items, setItems] = useState([]);
  4.   const [loading, setLoading] = useState(false);
  5.   const [page, setPage] = useState(1);
  6.   const loaderRef = useRef(null);
  7.   // 模拟加载更多数据的函数
  8.   const loadMoreData = () => {
  9.     if (loading) return; // 防止重复加载
  10.     setLoading(true);
  11.     // 模拟异步数据请求
  12.     setTimeout(() => {
  13.       const newItems = Array.from({ length: 10 }, (_, index) => `Item ${(page - 1) * 10 + index + 1}`);
  14.       setItems((prevItems) => [...prevItems, ...newItems]);
  15.       setPage((prevPage) => prevPage + 1);
  16.       setLoading(false);
  17.     }, 1000); // 模拟请求延时
  18.   };
  19.   useEffect(() => {
  20.     // 创建 IntersectionObserver
  21.     const observer = new IntersectionObserver(
  22.       ([entry]) => {
  23.         if (entry.isIntersecting) {
  24.           loadMoreData(); // 当加载元素进入视口时,触发加载更多数据
  25.         }
  26.       },
  27.       {
  28.         rootMargin: '0px', // 可根据需要调整,决定何时触发
  29.         threshold: 1.0, // 触发条件:元素完全进入视口
  30.       }
  31.     );
  32.     // 启动观察
  33.     if (loaderRef.current) {
  34.       observer.observe(loaderRef.current);
  35.     }
  36.     // 清理 observer
  37.     return () => {
  38.       if (loaderRef.current) {
  39.         observer.unobserve(loaderRef.current);
  40.       }
  41.     };
  42.   }, [loading, page]);
  43.   return (
  44.     <div>
  45.       <div>
  46.         {items.map((item, index) => (
  47.           <div key={index}>{item}</div>
  48.         ))}
  49.       </div>
  50.       {/* 触底加载元素 */}
  51.       <div ref={loaderRef}>
  52.         {loading ? <p>Loading...</p> : <p>Scroll down to load more...</p>}
  53.       </div>
  54.     </div>
  55.   );
  56. };
  57. export default InfiniteScroll;
复制代码
原生js中用法 

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>Infinite Scroll with IntersectionObserver</title>
  7.     <style>
  8.         body {
  9.             font-family: Arial, sans-serif;
  10.             padding: 0;
  11.             margin: 0;
  12.             height: 2000px; /* Just to make the page scrollable */
  13.         }
  14.         .item {
  15.             padding: 10px;
  16.             margin: 10px 0;
  17.             background-color: #f4f4f4;
  18.             border: 1px solid #ddd;
  19.         }
  20.         #loading {
  21.             text-align: center;
  22.             padding: 10px;
  23.             background-color: #f1f1f1;
  24.         }
  25.     </style>
  26. </head>
  27. <body>
  28.     <div id="content">
  29.         <!-- 初始内容 -->
  30.         <div class="item">Item 1</div>
  31.         <div class="item">Item 2</div>
  32.         <div class="item">Item 3</div>
  33.         <div class="item">Item 4</div>
  34.         <div class="item">Item 5</div>
  35.     </div>
  36.    
  37.     <!-- 加载更多的提示 -->
  38.     <div id="loading">Loading more...</div>
  39.     <script>
  40.         // 模拟加载更多数据的函数
  41.         let page = 1;
  42.         const loadMoreData = () => {
  43.             // 模拟异步请求数据
  44.             setTimeout(() => {
  45.                 const content = document.getElementById('content');
  46.                 for (let i = 0; i < 5; i++) {
  47.                     const newItem = document.createElement('div');
  48.                     newItem.classList.add('item');
  49.                     newItem.textContent = `Item ${page * 5 + i + 1}`;
  50.                     content.appendChild(newItem);
  51.                 }
  52.                 page++;
  53.             }, 1000); // 模拟1秒的延迟
  54.         };
  55.         // 设置 IntersectionObserver 监听“加载更多”元素
  56.         const loadingElement = document.getElementById('loading');
  57.         const observer = new IntersectionObserver((entries, observer) => {
  58.             // 只在元素完全进入视口时触发
  59.             entries.forEach(entry => {
  60.                 if (entry.isIntersecting) {
  61.                     loadMoreData();
  62.                     observer.unobserve(loadingElement); // 停止监听当前元素
  63.                     observer.observe(loadingElement); // 重新开始监听
  64.                 }
  65.             });
  66.         }, {
  67.             rootMargin: '0px',
  68.             threshold: 1.0 // 完全进入视口时触发
  69.         });
  70.         // 启动 IntersectionObserver
  71.         observer.observe(loadingElement);
  72.     </script>
  73. </body>
  74. </html>
复制代码
Vue2中利用

  1. <template>
  2.   <div>
  3.     <!-- 内容部分 -->
  4.     <div class="content">
  5.       <div v-for="(item, index) in items" :key="index" class="item">
  6.         {{ item }}
  7.       </div>
  8.     </div>
  9.     <!-- 加载更多提示 -->
  10.     <div id="loading" class="loading">加载更多...</div>
  11.   </div>
  12. </template>
  13. <script>
  14. export default {
  15.   data() {
  16.     return {
  17.       items: ['Item 1', 'Item 2', 'Item 3'], // 初始数据
  18.       page: 1, // 当前页数
  19.     };
  20.   },
  21.   mounted() {
  22.     // 设置 IntersectionObserver 监听加载更多区域
  23.     const loadingElement = document.getElementById('loading');
  24.     const observer = new IntersectionObserver(this.handleIntersection, {
  25.       rootMargin: '0px',
  26.       threshold: 1.0, // 完全进入视口时触发
  27.     });
  28.     observer.observe(loadingElement);
  29.   },
  30.   methods: {
  31.     handleIntersection(entries, observer) {
  32.       entries.forEach((entry) => {
  33.         if (entry.isIntersecting) {
  34.           // 如果加载更多区域进入视口,加载更多数据
  35.           this.loadMoreData();
  36.         }
  37.       });
  38.     },
  39.     loadMoreData() {
  40.       setTimeout(() => {
  41.         const newItems = Array.from({ length: 5 }, (_, i) => `Item ${this.page * 5 + i + 1}`);
  42.         this.items.push(...newItems); // 添加新数据
  43.         this.page += 1; // 增加页码
  44.       }, 1000); // 模拟网络请求延时
  45.     },
  46.   },
  47. };
  48. </script>
  49. <style>
  50. .content {
  51.   height: 1500px; /* 让页面滚动 */
  52. }
  53. .item {
  54.   padding: 10px;
  55.   margin: 10px 0;
  56.   background-color: #f4f4f4;
  57.   border: 1px solid #ddd;
  58. }
  59. .loading {
  60.   text-align: center;
  61.   padding: 10px;
  62.   background-color: #f1f1f1;
  63. }
  64. </style>
复制代码
Vue3中利用

  1. <template>
  2.   <div>
  3.     <!-- 内容部分 -->
  4.     <div class="content">
  5.       <div v-for="(item, index) in items" :key="index" class="item">
  6.         {{ item }}
  7.       </div>
  8.     </div>
  9.     <!-- 加载更多提示 -->
  10.     <div id="loading" class="loading">加载更多...</div>
  11.   </div>
  12. </template>
  13. <script>
  14. import { ref, onMounted } from 'vue';
  15. export default {
  16.   setup() {
  17.     const items = ref(['Item 1', 'Item 2', 'Item 3']); // 初始数据
  18.     const page = ref(1); // 当前页数
  19.     // 加载更多数据的函数
  20.     const loadMoreData = () => {
  21.       setTimeout(() => {
  22.         const newItems = Array.from({ length: 5 }, (_, i) => `Item ${page.value * 5 + i + 1}`);
  23.         items.value.push(...newItems); // 添加新数据
  24.         page.value += 1; // 增加页码
  25.       }, 1000); // 模拟网络请求延时
  26.     };
  27.     // 处理 IntersectionObserver 逻辑
  28.     const handleIntersection = (entries, observer) => {
  29.       entries.forEach((entry) => {
  30.         if (entry.isIntersecting) {
  31.           loadMoreData(); // 如果加载更多区域进入视口,加载更多数据
  32.         }
  33.       });
  34.     };
  35.     // 在组件挂载时设置 IntersectionObserver
  36.     onMounted(() => {
  37.       const loadingElement = document.getElementById('loading');
  38.       const observer = new IntersectionObserver(handleIntersection, {
  39.         rootMargin: '0px',
  40.         threshold: 1.0,
  41.       });
  42.       observer.observe(loadingElement);
  43.     });
  44.     return { items };
  45.   },
  46. };
  47. </script>
  48. <style>
  49. .content {
  50.   height: 1500px; /* 让页面滚动 */
  51. }
  52. .item {
  53.   padding: 10px;
  54.   margin: 10px 0;
  55.   background-color: #f4f4f4;
  56.   border: 1px solid #ddd;
  57. }
  58. .loading {
  59.   text-align: center;
  60.   padding: 10px;
  61.   background-color: #f1f1f1;
  62. }
  63. </style>
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金歌

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表