react 无限下拉搭配 intersection-observer

npm i intersection-observer
// 顶部引入
import 'intersection-observer';
// 字段解析
loadingText: PropTypes.string, // 加载文字
loadingIon: PropTypes.any, // 加载图标 不添加为默认
finish: PropTypes.bool, // 是否完成
next: PropTypes.func, // 下一次触发的函数

0.初始准备工作

constructor(props) {
    super(props);
    this.state = {
       loading: false,
     };
     // 获取当前的ref好控制当前元素是否到视窗
     this.ref = React.createRef();
}

1.一开始先定义好intersection-observer

    componentDidMount() {
     // IntersectionObserver polyfill 文档添加
     IntersectionObserver.prototype.USE_MUTATION_OBSERVER = false;
 
     const node = this.ref.current;
     this.observer = new IntersectionObserver((entries, observer) => {
       entries.forEach((entry) => {
         if (entry.isIntersecting) {
         // 添加判断显示的是否为加载还是完成
           this.setState({ loading: true });
         // 暂停监听 避免再loading时还触发
           observer.unobserve(node);
        // 调用方法
           this.dataLoading();
         }
       });
     }, {
       // 增加视口 范围
       rootMargin: '0px 0px 100px 0px',
     });
     this.observer.POLL_INTERVAL = 500;
     this.observer.USE_MUTATION_OBSERVER = false;
     this.observer.observe(node);  // 运行
   }
 
   componentWillUnmount() {
     this.listener1.remove(); // 销毁时删除
   } 

3.被调用时执行的函数

async dataLoading() {
    try {
       await this.props.next();  // 调用传入的方法 用于loading数据
     } finally {
       this.setState({ loading: false });
       if (!this.props.finish) { // finish判断是否已经完成达到了最后一条数据
        this.observer.observe(this.ref.current);
      }
   }
}

4.显示的样式

renderContent() {
    const { loadingText, loadingIon, finish, next, ...layoutProps } = this.props;
     const { loading } = this.state;
     return (
      <FlexRowContainer
        {...layoutProps}
        width="match_parent"
         height="20px"
        justifyContent="center"
         ref={this.ref} // 获取ref
         fontSize="14px"
       >
         {loading && // 为加载时显示的样式
         <FlexRowContainer
           width="wrap_content"
           height="wrap_content"
           fontSize="13px"
         >
           <scmp.Span
             width="wrap_content"
             height="wrap_content"
             fontSize="13px"
           >
             {loadingText || 'loading'}
           </scmp.Span>
           {loadingIon || <DotLoading />}
         </FlexRowContainer>}
         {finish && // 完成时显示的样式
         <scmp.Span
           width="wrap_content"
           height="wrap_content"
           fontSize="12px"
         >
           --- There are no more goods ---
         </scmp.Span>}
       </FlexRowContainer>
     );
  } 

5.完整代码

  1 class ScrollLoad extends BaseComponent {
 2   constructor(props) {
 3     super(props);
 4     this.state = {
 5       loading: false,
 6     };
 7     // 获取当前的ref好控制当前元素是否到视窗
 8     this.ref = React.createRef();
 9   }
10 
11   componentDidMount() {
12     // IntersectionObserver polyfill 文档添加
13     IntersectionObserver.prototype.USE_MUTATION_OBSERVER = false;
14 
15     const node = this.ref.current;
16     this.observer = new IntersectionObserver((entries, observer) => {
17       entries.forEach((entry) => {
18         if (entry.isIntersecting) {
19         // 添加判断显示的是否为加载还是完成
20           this.setState({ loading: true });
21         // 暂停监听 避免再loading时还触发
22           observer.unobserve(node);
23        // 调用方法
24           this.dataLoading();
25         }
26       });
27     }, {
28       // 增加视口 范围
29       rootMargin: '0px 0px 100px 0px',
30     });
31     this.observer.POLL_INTERVAL = 500;
32     this.observer.USE_MUTATION_OBSERVER = false;
33     this.observer.observe(node);  // 运行
34   }
35 
36   componentWillUnmount() {
37     this.listener1.remove(); // 销毁时删除
38   }
39 
40   async dataLoading() {
41     try {
42       await this.props.next();  // 调用传入的方法 用于loading数据
43     } finally {
44       this.setState({ loading: false });
45       if (!this.props.finish) { // finish判断是否已经完成达到了最后一条数据
46         this.observer.observe(this.ref.current);
47       }
48     }
49   }
50 
51   renderContent() {
52     const { loadingText, loadingIon, finish, next, ...layoutProps } = this.props;
53     const { loading } = this.state;
54     return (
55       <FlexRowContainer
56         {...layoutProps}
57         width="match_parent"
58         height="20px"
59         justifyContent="center"
60         ref={this.ref}
61         fontSize="14px"
62       >
63         {loading &&
64         <FlexRowContainer
65           width="wrap_content"
66           height="wrap_content"
67           fontSize="13px"
68         >
69           <scmp.Span
70             width="wrap_content"
71             height="wrap_content"
72             fontSize="13px"
73           >
74             {loadingText || 'loading'}
75           </scmp.Span>
76           {loadingIon || <DotLoading />}
77         </FlexRowContainer>}
78         {finish &&
79         <scmp.Span
80           width="wrap_content"
81           height="wrap_content"
82           fontSize="12px"
83         >
84           --- There are no more goods ---
85         </scmp.Span>}
86       </FlexRowContainer>
87     );
88   }
89           

 

posted @ 2023-03-06 16:56  马铃薯头抽雪茄  阅读(238)  评论(0)    收藏  举报