You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用React按邮轮公司展示邮轮列表并实现展开收起功能

解决邮轮公司分组与展开收起列表的方案

嘿,我来帮你搞定这个分组展示邮轮的问题!要实现按邮轮公司分组+展开收起的功能,咱们可以分成两步走:先把邮轮数据按公司分组,再集成Accordion组件实现展开收起。下面是具体的实现方案:

1. 先处理数据分组

首先需要把你的shipList数组按照cruise_line字段进行分组。咱们可以写一个工具函数,用数组的reduce方法来完成这个逻辑:

const groupShipsByCruiseLine = (ships) => {
  return ships.reduce((groups, ship) => {
    const cruiseLine = ship.cruise_line || '未归属公司'; // 处理没有cruise_line的异常情况
    if (!groups[cruiseLine]) {
      groups[cruiseLine] = [];
    }
    groups[cruiseLine].push(ship);
    return groups;
  }, {});
};

这个函数会把原始的邮轮数组转换成一个对象,键是邮轮公司名称,值是对应公司的邮轮数组,方便后续按组渲染。

2. 集成Accordion组件实现展开收起

这里我用React Bootstrap的Accordion组件来实现(如果还没安装依赖,先执行npm install react-bootstrap bootstrap),当然你也可以用其他UI库的Accordion,或者自己实现一个简易版。

下面是修改后的完整ListofShips组件代码:

import React from 'react';
import { Link } from 'react-router-dom';
import { Accordion, Card, Button } from 'react-bootstrap'; // 导入Accordion相关组件
import { getAllShips } from '../api/api';

class ListofShips extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      shipList: [],
      expandedCruiseLine: null, // 控制当前展开的面板,默认全部收起
    };
    this.setUpShips = this.setUpShips.bind(this);
    this.toggleAccordion = this.toggleAccordion.bind(this);
  }

  componentDidMount() {
    this.setUpShips();
  }

  setUpShips() {
    getAllShips()
      .then(res => {
        this.setState({ shipList: res });
      });
  }

  // 切换Accordion的展开/收起状态
  toggleAccordion(cruiseLine) {
    this.setState(prevState => ({
      expandedCruiseLine: prevState.expandedCruiseLine === cruiseLine ? null : cruiseLine,
    }));
  }

  // 分组数据的工具函数
  groupShipsByCruiseLine(ships) {
    return ships.reduce((groups, ship) => {
      const cruiseLine = ship.cruise_line || '未归属公司';
      if (!groups[cruiseLine]) {
        groups[cruiseLine] = [];
      }
      groups[cruiseLine].push(ship);
      return groups;
    }, {});
  }

  render() {
    const groupedShips = this.groupShipsByCruiseLine(this.state.shipList);
    // 把分组后的对象转换成数组,方便遍历渲染
    const cruiseLines = Object.entries(groupedShips);

    return (
      <Accordion>
        {cruiseLines.map(([cruiseLine, ships]) => (
          <Card key={cruiseLine}>
            <Card.Header>
              <Button
                variant="link"
                onClick={() => this.toggleAccordion(cruiseLine)}
                className="w-100 text-left"
              >
                {cruiseLine} ({ships.length}艘邮轮)
              </Button>
            </Card.Header>
            {this.state.expandedCruiseLine === cruiseLine && (
              <Accordion.Collapse eventKey={cruiseLine}>
                <Card.Body>
                  <ul className="shipsList">
                    {ships.map(ship => (
                      <li key={ship.id}>
                        <Link to={`/ship/${ship.id}`}>{ship.ship_name}</Link>
                      </li>
                    ))}
                  </ul>
                </Card.Body>
              </Accordion.Collapse>
            )}
          </Card>
        ))}
      </Accordion>
    );
  }
}

export default ListofShips;

关键逻辑说明

  • 数据分组:通过groupShipsByCruiseLine把原始数据整理成按公司分组的结构,让后续渲染逻辑更清晰。
  • 展开收起控制:用expandedCruiseLine状态记录当前展开的公司面板,点击按钮时切换状态,控制对应面板内容的显示/隐藏。
  • UI渲染:遍历每个邮轮公司生成对应的Accordion面板,面板展开后展示该公司下的所有邮轮列表,同时在标题上标注邮轮数量提升用户体验。

如果你不想依赖第三方UI库,也可以自己写一个简易版Accordion:核心逻辑就是通过状态控制面板内容的display属性(block/none),同样能实现展开收起效果。

内容的提问来源于stack exchange,提问作者Rob Wilkinson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:49:17