如何在Astro中用JS/JSX先按团队再按年份分组球员数据?
Astro实现球员数据按团队+年份分组展示方案
我使用Astro框架开发,现有接口返回的JSON数据如下,需要实现先按团队、再按年份分组展示球员,最终HTML要匹配指定格式。目前代码能正常运行但未实现分组效果,求修改前置脚本(frontmatter)和页面主体的代码。
给定的JSON响应数据
{ "data": [ { "id": 1, "team_name": "Team One", "players": [ { "player_name": "Mickey Mantle", "players_year": { "year": 2024 } }, { "player_name": "Larry Smalls", "players_year": { "year": 2022 } }, { "player_name": "Ron Davis", "players_year": { "year": 2024 } } ] }, { "id": 2, "team_name": "Team Two", "players": [ { "player_name": "Jim Abbot", "players_year": { "year": 2022 } } ] } ] }
期望的HTML输出
<div class="group"> <h2>Team One</h2> <h3>2022</h3> <ul> <li>Larry Smalls</li> </ul> <h3>2024</h3> <ul> <li>Mickey Mantle</li> <li>Ron Davis</li> </ul> </div> <div class="group"> <h2>Team Two</h2> <h3>2022</h3> <ul> <li>Jim Abbot</li> </ul> </div>
当前的teams.astro代码
前置脚本
--- const directus = await getDirectusClient() const response = await directus.items("teams").readByQuery({ fields: [ "id", "team_name", "players.player_name", "players.players_year.year", ], }) const formattedResponse = response.data.map((team) => { return { ...team, yearsArr: team.players.map(player => player.players_year.year) } }) const [...teams] = formattedResponse ---
页面主体
<h1>Teams Page</h1> { teams.map((team) => { return ( <div class='group'> <h2>{team.team_name}</h2> <ul> {team.players.map((player) => ( <li> {player.player_name} ({player.players_year.year}) </li> ))} </ul> </div> ) }) }
修改方案
一、前置脚本(Frontmatter)修改
在格式化数据时,新增按年份分组的球员结构,同时生成排序后的年份数组保证展示顺序:
--- const directus = await getDirectusClient() const response = await directus.items("teams").readByQuery({ fields: [ "id", "team_name", "players.player_name", "players.players_year.year", ], }) // 格式化数据:给每个团队添加按年份分组的球员列表 const formattedResponse = response.data.map((team) => { // 用reduce按年份分组球员 const playersByYear = team.players.reduce((acc, player) => { const year = player.players_year.year; // 初始化年份对应的空数组 if (!acc[year]) { acc[year] = []; } acc[year].push(player); return acc; }, {}); // 对年份进行升序排序,保证展示顺序正确 const sortedYears = Object.keys(playersByYear).sort((a, b) => a - b); return { ...team, playersByYear, // 按年份分组的球员对象 sortedYears // 排序后的年份数组 }; }) const [...teams] = formattedResponse ---
二、页面主体代码修改
遍历团队后,再遍历排序后的年份,渲染对应年份的球员列表:
<h1>Teams Page</h1> { teams.map((team) => { return ( <div class='group'> <h2>{team.team_name}</h2> {team.sortedYears.map((year) => { const yearPlayers = team.playersByYear[year]; return ( <> <h3>{year}</h3> <ul> {yearPlayers.map((player) => ( <li>{player.player_name}</li> ))} </ul> </> ); })} </div> ); }) }
完整teams.astro代码
--- const directus = await getDirectusClient() const response = await directus.items("teams").readByQuery({ fields: [ "id", "team_name", "players.player_name", "players.players_year.year", ], }) const formattedResponse = response.data.map((team) => { const playersByYear = team.players.reduce((acc, player) => { const year = player.players_year.year; if (!acc[year]) { acc[year] = []; } acc[year].push(player); return acc; }, {}); const sortedYears = Object.keys(playersByYear).sort((a, b) => a - b); return { ...team, playersByYear, sortedYears }; }) const [...teams] = formattedResponse --- <h1>Teams Page</h1> { teams.map((team) => { return ( <div class='group'> <h2>{team.team_name}</h2> {team.sortedYears.map((year) => { const yearPlayers = team.playersByYear[year]; return ( <> <h3>{year}</h3> <ul> {yearPlayers.map((player) => ( <li>{player.player_name}</li> ))} </ul> </> ); })} </div> ); }) }
内容的提问来源于stack exchange,提问作者scottrod
相关产品推荐
相关产品推荐

