构建可折叠的 React 手风琴

ReactReactBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本实验中,我们将探索如何使用组件和钩子在 React 中实现一个可折叠的手风琴菜单。本实验的目的是提供一个实践经验,用于构建一个具有多个可折叠内容元素的功能性手风琴菜单。在本实验结束时,你将很好地理解如何使用 React 创建动态和交互式用户界面。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL react(("React")) -.-> react/AdvancedConceptsGroup(["Advanced Concepts"]) react(("React")) -.-> react/StateManagementGroup(["State Management"]) react(("React")) -.-> react/FundamentalsGroup(["Fundamentals"]) react/FundamentalsGroup -.-> react/jsx("JSX") react/FundamentalsGroup -.-> react/event_handling("Handling Events") react/FundamentalsGroup -.-> react/conditional_render("Conditional Rendering") react/AdvancedConceptsGroup -.-> react/hooks("React Hooks") react/StateManagementGroup -.-> react/use_state_reducer("Using useState and useReducer") subgraph Lab Skills react/jsx -.-> lab-38339{{"构建可折叠的 React 手风琴"}} react/event_handling -.-> lab-38339{{"构建可折叠的 React 手风琴"}} react/conditional_render -.-> lab-38339{{"构建可折叠的 React 手风琴"}} react/hooks -.-> lab-38339{{"构建可折叠的 React 手风琴"}} react/use_state_reducer -.-> lab-38339{{"构建可折叠的 React 手风琴"}} end

可折叠手风琴

VM 中已经提供了 index.htmlscript.js。一般来说,你只需要在 script.jsstyle.css 中添加代码。

要渲染一个带有多个可折叠内容元素的手风琴菜单,你可以按照以下步骤操作:

  1. 定义一个 AccordionItem 组件,该组件渲染一个 <button>,并在通过 handleClick 回调通知其父组件的同时更新组件。
  2. AccordionItem 中使用 isCollapsed 属性来确定其外观并设置其 className
  3. 定义一个 Accordion 组件,并使用 useState() 钩子将 bindIndex 状态变量的值初始化为 defaultIndex
  4. 通过识别函数名称来过滤 children,以删除不必要的节点,AccordionItem 除外。
  5. 对收集到的节点使用 Array.prototype.map() 来渲染各个可折叠元素。
  6. 定义 changeItem,它将在点击 AccordionItem<button> 时执行。
  7. changeItem 执行传递的回调 onItemClick,并根据点击的元素更新 bindIndex

以下是代码:

.accordion-item.collapsed {
  display: none;
}

.accordion-item.expanded {
  display: block;
}

.accordion-button {
  display: block;
  width: 100%;
}
const AccordionItem = ({ label, isCollapsed, handleClick, children }) => {
  return (
    <>
      <button className="accordion-button" onClick={handleClick}>
        {label}
      </button>
      <div
        className={`accordion-item ${isCollapsed ? "collapsed" : "expanded"}`}
        aria-expanded={isCollapsed}
      >
        {children}
      </div>
    </>
  );
};

const Accordion = ({ defaultIndex, onItemClick, children }) => {
  const [bindIndex, setBindIndex] = React.useState(defaultIndex);

  const changeItem = (itemIndex) => {
    if (typeof onItemClick === "function") onItemClick(itemIndex);
    if (itemIndex !== bindIndex) setBindIndex(itemIndex);
  };

  const items = children.filter((item) => item.type.name === "AccordionItem");

  return (
    <>
      {items.map(({ props }) => (
        <AccordionItem
          isCollapsed={bindIndex !== props.index}
          label={props.label}
          handleClick={() => changeItem(props.index)}
          children={props.children}
        />
      ))}
    </>
  );
};
ReactDOM.createRoot(document.getElementById("root")).render(
  <Accordion defaultIndex="1" onItemClick={console.log}>
    <AccordionItem label="A" index="1">
      Lorem ipsum
    </AccordionItem>
    <AccordionItem label="B" index="2">
      Dolor sit amet
    </AccordionItem>
  </Accordion>
);

请点击右下角的“Go Live”以在端口 8080 上运行 Web 服务。然后,你可以刷新“Web 8080”标签页来预览网页。

总结

恭喜你!你已经完成了可折叠手风琴实验。你可以在 LabEx 中练习更多实验来提升你的技能。