组件代码
/* eslint-disable no-return-assign */
import React, { Component } from "react";
import { ActivityIndicator, Toast } from "antd-mobile";
import EmptyImage from "@/components/EmptyImage";
import { touchEvent } from "@/utils/commonUtil";
import style from "./index.less";
/**
* 上拉加载
* @params { 是否正在加载 } loading
* @params { 加载数据事件 } loadData
* @params { 自定义列表卡片 } ItemDom
* @params { 列表数据 } data
* @params { 是否有更多 } isMore
* @params { 当前页 } page
* @params { 全部页 } totalPages
*/
interface Props {
data: any[];
ItemDom: any;
loading: boolean;
loadData: Function; // 加载数据事件
isMore: boolean; // 是否有更多
}
interface State {
backTopFlag: boolean;
isUp: boolean;
}
class Index extends Component<Props, State> {
scrollBox: any;
scrollContent: any;
state = {
backTopFlag: false,
isUp: false,
};
componentDidMount() {
this.init();
}
componentWillUnmount() {
this.scrollBox.removeEventListener("scroll", this.scrollshi, false);
}
init = () => {
this.scrollBox.addEventListener("scroll", this.scrollshi, false);
// 向下滑
touchEvent.swipeDown(window, this.scrollDown);
// 向上滑
touchEvent.swipeUp(window, this.scrollUp);
};
scrollDown = () => {
const { isUp } = this.state;
if (!isUp) return;
this.setState({
isUp: false,
});
};
scrollUp = () => {
const { isUp } = this.state;
if (isUp) return;
this.setState({
isUp: true,
});
};
// 触底事件
touchBottom = () => {
const { loadData, loading, isMore } = this.props;
if (loading || !isMore) return;
loadData();
};
scrollshi = () => {
let flag = false;
const { backTopFlag } = this.state;
const { loading, isMore } = this.props;
if (
this.scrollContent.offsetHeight -
this.scrollBox.offsetHeight -
this.scrollBox.scrollTop <=
350 &&
!flag
) {
flag = true;
setTimeout(() => {
this.touchBottom();
flag = false;
}, 500);
}
if (
this.scrollContent.offsetHeight -
this.scrollBox.offsetHeight -
this.scrollBox.scrollTop <=
0 &&
!loading &&
!isMore
) {
Toast.info("加载到底了~");
}
if (this.scrollBox.scrollTop > 1200) {
if (backTopFlag) return;
this.setState({
backTopFlag: true,
});
} else {
if (!backTopFlag) return;
this.setState({
backTopFlag: false,
});
}
};
render() {
const { data, ItemDom, loading } = this.props;
const { backTopFlag, isUp } = this.state;
return (
<div
className={style.scrollBox}
ref={(scrollBox) => (this.scrollBox = scrollBox)}
>
<div
className={style.scrollContent}
ref={(scrollContent) => (this.scrollContent = scrollContent)}
>
{data && data[0] ? (
data?.map((item, index) => (
<ItemDom key={`${item.id}${index}`} item={item} />
))
) : (
<EmptyImage type={6} />
)}
{loading && (
<div className={style.loading}>
<ActivityIndicator text="loading..." />
</div>
)}
</div>
{backTopFlag && isUp && false && (
<div className={style.goTop}>1111</div>
)}
</div>
);
}
}
export default Index;
样式
.scrollBox {
width: 100%;
height: 100%;
overflow-y: auto;
.scrollContent {
width: 100%;
}
.loading {
width: 100%;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
}
}
.goTop {
position: fixed;
right: 10px;
bottom: 90px;
z-index: 9999999;
width: 70px;
height: 70px;
background-color: saddlebrown;
opacity: 0;
}
使用方法
<!--
* @Descripttion:
* @version:
* @Author: WangPeng
* @Date: 2021-10-22 18:38:22
* @LastEditors: WangPeng
* @LastEditTime: 2021-11-15 11:29:50
-->
### 实现滚动加载
## 代码演示
```javascript
import ScrollList from "@/components/ScrollList";
/**
* 上拉加载
* @params { 是否正在加载 } loading
* @params { 加载数据事件 } loadData
* @params { 自定义列表卡片 } ItemDom
* @params { 列表数据 } data
* @params { 是否有更多 } isMore
* @params { 当前页 } page
* @params { 全部页 } totalPages
*/
export default class TestPage extends Component {
render() {
return (
<div>
<ScrollList
loading={loading}
loadData={this.loadData}
ItemDom={Card}
data={list}
isMore={page < totalPages>}
/>
</div>
);
}
}
注意事项
一定要限制包裹这个组件的盒子的最大高度,不然无法实现滚动加载。