我有一个包含其他数组的数组:
export const ArtifactArray = [
AccessoriesArtifacts,
BodyArtifacts,
CloakArtifacts,
FeetArtifacts,
HandsArtifacts,
HeadArtifacts,
LeftHandArtifacts,
MainHandArtifacts,
NeckArtifacts
]
这些数组中的每一个都包含对象:
export const BodyArtifacts = [
WonderArmor,
BrimstoneBreastplate,
PetrifiedWoodBreastplate,
DragonScaleArmor,
RibCage,
GreatBasilistScales,
TitansCuirass,
CyclopsKingTunic,
];
稍后我将遍历数组并在屏幕上显示所有这些对象,如下所示:
{ArtifactArray.map((array, index) => (
<Fragment key={index}>
{array.map((artifact, index) => (
<ArtifactsBlock
key={index}
src={artifact.pic}
name={artifact.name}
/>
))}
</Fragment>
))}
一切正常。
然后我试图给它添加一个分页,这就是问题开始的地方。我想每页只返回 20 个对象(总共 120 个)。但是,如果这些数组中每个对象的数量不同,我该怎么做呢?如果我在其中一些数组的末尾使用 array.slice(0, 20)、array.slice(20, 40) 等,它将返回 11 或 9。当然,我可以去掉那些内部数组并简单地将所有对象集中到一个数组中,但这太笨重了。我想保持现在的样子。
如何展平你的清单?
{ArtifactArray.flat().slice(i, i + pageLen).map(artifact, index) => (
<ArtifactsBlock
key={index}
src={artifact.pic}
name={artifact.name}
/>
)}
您可以 flatten 将对象数组缩小为一个数组,然后使用该数组的长度加上要显示的项目数的“限制”来确定您将如何分割数据。
这是一个使用小型数据集(总共 11 个项目)的小型工作示例。数据被展平并传递到组件中。有两种状态:一种是页面状态,一种是限制状态。注意:这里的限制设置为每页两个项目。
渲染组件时,它会同时调用
getPages
和getArtifacts
函数。他们使用页面和限制状态中的信息构建了一系列页面按钮和一系列工件。
const { useState } = React;
function Example({ artifacts }) {
const [ page, setPage ] = useState(0);
const [ limit, setLimit ] = useState(2);
// Return a subset of data from the artifacts state based
// on the page number, and the page limit
function getArtifacts() {
return artifacts
.slice(page * limit, (page * limit) + limit)
.map(artifact => {
return (
<Artifact
key={artifact.id}
data={artifact}
/>
);
});
}
// Update the page state
function handlePage(e) {
const { dataset: { page } } = e.target;
setPage(+page);
}
// Create a series of pages based on the number of objects
// in the artifacts state, and the page limit. Add an active prop
// to indicate which page button should be highlighted
function getPages() {
const arr = [];
const mod = artifacts.length / limit;
const pages = mod % limit === 0 ? mod : Math.floor(mod) + 1;
for (let p = 0; p < pages; p++) {
arr.push((
<Page
key={p}
number={p}
active={p === page}
handlePage={handlePage}
/>)
);
}
return arr;
}
// Get the pages and the artifacts
return (
<main>
<h2>Artifacts</h2>
<section className="pages">
{getPages()}
</section>
<section className="artifacts">
{getArtifacts()}
</section>
</main>
);
}
// Return an artifact name
function Artifact({ data }) {
return <section><h4>{data.name}</h4></section>;
}
// Return a page
function Page({ number, active, handlePage }) {
const cn = ['page', active && 'active'].join(' ');
return (
<button
className={cn}
data-page={number}
type="button"
onClick={handlePage}
>{number + 1}
</button>
);
}
const bodyArtifacts=[{id:"ba1",name:"WonderArmor"},{id:"ba2",name:"BrimstoneBreastplate"},{id:"ba3",name:"PetrifiedWoodBreastplate"},{id:"ba4",name:"DragonScaleArmor"},{id:"ba5",name:"GreatBasilistScales"},{id:"ba6",name:"TitansCuirass"},{id:"ba7",name:"CyclopsKingTunic"}];
const cloakArtifacts=[{id:"ca1",name:"RedCloak"},{id:"ca2",name:"BlueCloak"},{id:"ca3",name:"PinkCloak"},{id:"ca4",name:"GoldCloak"}];
const artifacts=[bodyArtifacts,cloakArtifacts];
const node = document.getElementById('root');
const root = ReactDOM.createRoot(node);
// Pass in the flattened data
root.render(<Example artifacts={artifacts.flat()} />);
.page { width: 30px; aspect-ratio: 1; border-radius: 5px;}
.page:not(:last-child) { margin-right: 0.25rem; }
.page:hover:not(.active) { background-color: #fffff0; cursor: pointer; }
.active { background-color: lightgreen; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root"></div>