c
复制代码
import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch, useLocation } from "dva";
import styles from './index.less';
const List = () => {
const location = useLocation();
// 解析查询参数(需手动处理)
const searchParams = new URLSearchParams(location.search);
const dispatch = useDispatch();
const [loading, setLoading] = useState(false); // 加载状态
const [finished, setFinished] = useState(false); // 是否加载完成
const [page, setPage] = useState(1); // 当前页码
const [pageSize, setPageSize] = useState(10); // 每页显示条数
const [data, setData] = useState([]); // 当前显示的所有数据
const [screenHeight, setScreenHeight] = useState(window.innerHeight); // 当前屏幕高度
// 获取屏幕高度并监听窗口大小变化
useEffect(() => {
const handleResize = () => {
setScreenHeight(window.innerHeight);
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
// 请求接口数据
const getList = async (page) => {
if (loading || finished) return;
setLoading(true);
try {
dispatch({
type: "",
payload: {
url:
`你的接口`,
type: "POST",
body: {
page: page,
rows: pageSize
},
header: { "你的请求头参数" },
},
callback: res => {
if (res.result === "1" && res.rows.length > 0) {
setData((prevData) => [...prevData, ...res.rows]); // 追加新数据
if (res.rows.length < pageSize) {
setFinished(true); // 如果返回数据不足一页,说明没有更多数据
}
} else {
setFinished(true); // 接口无数据时停止加载
}
},
});
} catch (error) {
console.error("数据加载失败:", error);
} finally {
setLoading(false);
}
};
// 初始化加载第一页数据
useEffect(() => {
getList(1);
}, []);
// 监听滚动事件
useEffect(() => {
const container = document.querySelector(`.${styles.cardListContainer}`);
if (!container) return;
const handleScroll = () => {
const { scrollTop, clientHeight, scrollHeight } = container;
if (scrollTop + clientHeight >= scrollHeight - 10 && !loading && !finished) {
setPage((prevPage) => prevPage + 1); // 触底时分页加 1
}
};
container.addEventListener("scroll", handleScroll);
return () => container.removeEventListener("scroll", handleScroll);
}, [page, loading, finished]);
// 当分页变化时加载数据
useEffect(() => {
if (page > 1) {
getList(page); // 加载对应页的数据
}
}, [page]);
return (
<div
className={styles.cardListContainer}
style={{ height: screenHeight, overflowY: "auto" }} // 动态设置高度
>
{/* 卡片列表 */}
{data.map((item) => (
<div key={item.id} className={styles.card}>
<div className={styles.cardContent}>
<div>
<span className={styles.phone}>{item.phone}</span>
</div>
<div>
<span className={styles.remark}> {item.remark || "无备注"}</span>
</div>
</div>
</div>
))}
{/* 加载提示 */}
{loading && <div className={styles.loading}>加载中...</div>}
{/* 已加载全部数据提示 */}
{finished && <div className={styles.finished}>已显示全部数据</div>}
</div>
);
};
export default List;
c
复制代码
/* 卡片列表容器 */
.cardListContainer {
width: 100%;
margin: 0 auto;
padding: 0.2rem;
overflow-y: auto;
/* 支持内部滚动 */
background: #FFF;
padding-top: 0.85rem; // 留出一部分距离给导航栏
}
/* WebKit 内核浏览器补充 */
.cardListContainer::-webkit-scrollbar {
display: none;
}
/* 卡片样式 */
.card {
width: 100%;
padding: 0.2rem;
margin-bottom: 0.12rem;
display: flex;
flex-direction: column;
border-radius: 0.06rem;
background: rgba(0, 0, 0, 0.03);
}
.cardContent {
display: flex;
justify-content: space-between;
align-items: center;
div {
display: inline-grid;
}
.phone {
color: #101010;
font-size: 0.15rem;
font-style: normal;
font-weight: 300;
line-height: 0.24rem;
}
.remark {
color: rgba(29, 29, 30, 0.70);
font-size: 0.12rem;
font-style: normal;
font-weight: 300;
line-height: 0.18rem;
}
}
/* 加载提示 */
.loading {
text-align: center;
font-size: 0.12rem;
color: rgba(29, 29, 30, 0.20);
padding: 0.1rem;
}
/* 已加载全部数据提示 */
.finished {
text-align: center;
font-size: 0.12rem;
color: rgba(29, 29, 30, 0.20);
padding: 0.1rem;
}