组件代码

  1. /* eslint-disable no-return-assign */
  2. import React, { Component } from "react";
  3. import { ActivityIndicator, Toast } from "antd-mobile";
  4. import EmptyImage from "@/components/EmptyImage";
  5. import { touchEvent } from "@/utils/commonUtil";
  6. import style from "./index.less";
  7. /**
  8. * 上拉加载
  9. * @params { 是否正在加载 } loading
  10. * @params { 加载数据事件 } loadData
  11. * @params { 自定义列表卡片 } ItemDom
  12. * @params { 列表数据 } data
  13. * @params { 是否有更多 } isMore
  14. * @params { 当前页 } page
  15. * @params { 全部页 } totalPages
  16. */
  17. interface Props {
  18. data: any[];
  19. ItemDom: any;
  20. loading: boolean;
  21. loadData: Function; // 加载数据事件
  22. isMore: boolean; // 是否有更多
  23. }
  24. interface State {
  25. backTopFlag: boolean;
  26. isUp: boolean;
  27. }
  28. class Index extends Component<Props, State> {
  29. scrollBox: any;
  30. scrollContent: any;
  31. state = {
  32. backTopFlag: false,
  33. isUp: false,
  34. };
  35. componentDidMount() {
  36. this.init();
  37. }
  38. componentWillUnmount() {
  39. this.scrollBox.removeEventListener("scroll", this.scrollshi, false);
  40. }
  41. init = () => {
  42. this.scrollBox.addEventListener("scroll", this.scrollshi, false);
  43. // 向下滑
  44. touchEvent.swipeDown(window, this.scrollDown);
  45. // 向上滑
  46. touchEvent.swipeUp(window, this.scrollUp);
  47. };
  48. scrollDown = () => {
  49. const { isUp } = this.state;
  50. if (!isUp) return;
  51. this.setState({
  52. isUp: false,
  53. });
  54. };
  55. scrollUp = () => {
  56. const { isUp } = this.state;
  57. if (isUp) return;
  58. this.setState({
  59. isUp: true,
  60. });
  61. };
  62. // 触底事件
  63. touchBottom = () => {
  64. const { loadData, loading, isMore } = this.props;
  65. if (loading || !isMore) return;
  66. loadData();
  67. };
  68. scrollshi = () => {
  69. let flag = false;
  70. const { backTopFlag } = this.state;
  71. const { loading, isMore } = this.props;
  72. if (
  73. this.scrollContent.offsetHeight -
  74. this.scrollBox.offsetHeight -
  75. this.scrollBox.scrollTop <=
  76. 350 &&
  77. !flag
  78. ) {
  79. flag = true;
  80. setTimeout(() => {
  81. this.touchBottom();
  82. flag = false;
  83. }, 500);
  84. }
  85. if (
  86. this.scrollContent.offsetHeight -
  87. this.scrollBox.offsetHeight -
  88. this.scrollBox.scrollTop <=
  89. 0 &&
  90. !loading &&
  91. !isMore
  92. ) {
  93. Toast.info("加载到底了~");
  94. }
  95. if (this.scrollBox.scrollTop > 1200) {
  96. if (backTopFlag) return;
  97. this.setState({
  98. backTopFlag: true,
  99. });
  100. } else {
  101. if (!backTopFlag) return;
  102. this.setState({
  103. backTopFlag: false,
  104. });
  105. }
  106. };
  107. render() {
  108. const { data, ItemDom, loading } = this.props;
  109. const { backTopFlag, isUp } = this.state;
  110. return (
  111. <div
  112. className={style.scrollBox}
  113. ref={(scrollBox) => (this.scrollBox = scrollBox)}
  114. >
  115. <div
  116. className={style.scrollContent}
  117. ref={(scrollContent) => (this.scrollContent = scrollContent)}
  118. >
  119. {data && data[0] ? (
  120. data?.map((item, index) => (
  121. <ItemDom key={`${item.id}${index}`} item={item} />
  122. ))
  123. ) : (
  124. <EmptyImage type={6} />
  125. )}
  126. {loading && (
  127. <div className={style.loading}>
  128. <ActivityIndicator text="loading..." />
  129. </div>
  130. )}
  131. </div>
  132. {backTopFlag && isUp && false && (
  133. <div className={style.goTop}>1111</div>
  134. )}
  135. </div>
  136. );
  137. }
  138. }
  139. export default Index;

样式

  1. .scrollBox {
  2. width: 100%;
  3. height: 100%;
  4. overflow-y: auto;
  5. .scrollContent {
  6. width: 100%;
  7. }
  8. .loading {
  9. width: 100%;
  10. height: 100px;
  11. display: flex;
  12. align-items: center;
  13. justify-content: center;
  14. }
  15. }
  16. .goTop {
  17. position: fixed;
  18. right: 10px;
  19. bottom: 90px;
  20. z-index: 9999999;
  21. width: 70px;
  22. height: 70px;
  23. background-color: saddlebrown;
  24. opacity: 0;
  25. }

使用方法

  1. <!--
  2. * @Descripttion:
  3. * @version:
  4. * @Author: WangPeng
  5. * @Date: 2021-10-22 18:38:22
  6. * @LastEditors: WangPeng
  7. * @LastEditTime: 2021-11-15 11:29:50
  8. -->
  9. ### 实现滚动加载
  10. ## 代码演示
  11. ```javascript
  12. import ScrollList from "@/components/ScrollList";
  13. /**
  14. * 上拉加载
  15. * @params { 是否正在加载 } loading
  16. * @params { 加载数据事件 } loadData
  17. * @params { 自定义列表卡片 } ItemDom
  18. * @params { 列表数据 } data
  19. * @params { 是否有更多 } isMore
  20. * @params { 当前页 } page
  21. * @params { 全部页 } totalPages
  22. */
  23. export default class TestPage extends Component {
  24. render() {
  25. return (
  26. <div>
  27. <ScrollList
  28. loading={loading}
  29. loadData={this.loadData}
  30. ItemDom={Card}
  31. data={list}
  32. isMore={page < totalPages>}
  33. />
  34. </div>
  35. );
  36. }
  37. }

```

注意事项

一定要限制包裹这个组件的盒子的最大高度,不然无法实现滚动加载。