懒加载

import React, { useRef, useEffect, useState } from 'react';
import Item from './item';
import styles from './index.module.less';

const Home = () => {
  const [itemsObj, setItemObj] = useState({});
  const [prevScrollTop, setPrevScrollTop] = useState(0);
  const [data, setData] = useState([1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
  const homeRef = useRef(null);

  const computedItems = () => {
    const homeRect = homeRef.current.getBoundingClientRect();

    const items = document.getElementsByName('item');

    items.forEach((item) => {
      const itemRect = item.getBoundingClientRect();

      itemsObj[item.id] = { ...(itemsObj[item.id] || {}), itemRect };

      // 距离底部20px就加载
      itemsObj[item.id].intoViewport = itemsObj[item.id].intoViewport
        || (itemRect.top - homeRect.top) < homeRect.height + 20;
    });

    setItemObj({ ...itemsObj });
  };

  useEffect(() => {
    computedItems();
  }, []);

  return (
    
{ window.clearTimeout(homeRef.current.watchTimer); homeRef.current.watchTimer = setTimeout(() => { const { current } = homeRef; const direction = current.scrollTop - prevScrollTop > 0 ? 'down' : 'up'; // 向下滚动到离底部一段距离时,而且是第一次,就加载数据, // 这里通过prevScrollTop + current.clientHeight + 30 > current.scrollHeight来判断是否第一次 const bottomDis = 50; const isReachedBottom = prevScrollTop + current.clientHeight + bottomDis > current.scrollHeight; if (direction === 'down' && !isReachedBottom && current.scrollTop + current.clientHeight + bottomDis > current.scrollHeight) { const len = data.length; for (let i = len + 1; i < len + 10; i += 1) { data.push(i); } setData([...data]); } setPrevScrollTop(current.scrollTop); computedItems(); }, 50); }} > { data.map((i) => ( )) }
); }; export default Home;
import React from 'react';
import styles from './index.module.less';

export default class Item extends React.Component {
  render() {
    const { i, rect } = this.props;
    return (
      
{i}
{ rect.intoViewport ? '出现了' : '隐藏了'}
); } }
.home{
  flex: 1;
  margin: 12px;
  overflow: auto;
}
.item{
  position: relative;
  background: white;
  margin-bottom: 12px;
  height: 100px;
  border-radius: 8px;
  border: 1px solid #D9D9D9;
  &:after{
    position: absolute;
    content: '';
    bottom: 0;
    height: 8px;
    left: 0;
    right: 0;
    background: red;
  }
}

 

你可能感兴趣的:(前端)