React Visual - 手风琴 (advanced)

本贴最后更新于 1916 天前,其中的信息可能已经物是人非

2019-09-23

描述

渲染一个包含多个可折叠内容组件的手风琴菜单。

  • 定义一个 AccordionItem 组件,并将其传递给 Accordion。除了在 props.children 中函数名称标识为 AccordionItem 的节点外移除其余不必要的节点
  • 每一个 AccordionItem 组件都渲染一个 <button>,通过 props.handleClick 回调和传递到组件中的内容 props.children 来更新 Accordion。他们的展现通过 props.isCollapsed 及对应的 style 来确定
  • Accordion 组件中,使用 React.useState() hook 来初始化状态变量 bindIndex 的默认值为 props.defaultIndex
  • 在过滤出的节点中使用 Array.prototype.map 来渲染每一个可折叠的元素
  • 定义 changeItem 方法,在点击 AccordionItem 中的 <button> 时将会被执行。changeItem 执行传递的回调函数 onItemClick 并更新 bindIndex 为被点击元素的 index 属性值

实现

function AccordionItem(props) {
  const style = {
    collapsed: {
      display: 'none'
    },
    expanded: {
      display: 'block'
    },
    buttonStyle: {
      display: 'block',
      width: '100%'
    }
  };

  return (
    <div>
      <button style={style.buttonStyle} onClick={() => props.handleClick()}>
        {props.label}
      </button>
      <div
        className="collapse-content"
        style={props.isCollapsed ? style.collapsed : style.expanded}
        aria-expanded={props.isCollapsed}
      >
        {props.children}
      </div>
    </div>
  );
}

function Accordion(props) {
  const [bindIndex, setBindIndex] = React.useState(props.defaultIndex);

  const changeItem = itemIndex => {
    if (typeof props.onItemClick === 'function') props.onItemClick(itemIndex);
    if (itemIndex !== bindIndex) setBindIndex(itemIndex);
  };
  const items = props.children.filter(item => item.type.name === 'AccordionItem');

  return (
    <div className="wrapper">
      {items.map(({ props }) => (
        <AccordionItem
          isCollapsed={bindIndex !== props.index}
          label={props.label}
          handleClick={() => changeItem(props.index)}
          children={props.children}
        />
      ))}
    </div>
  );
}

使用

ReactDOM.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>,
  document.getElementById('root')
);

返回总目录

每天 30 秒系列之 React

  • 30Seconds

    📙 前端知识精选集,包含 HTML、CSS、JavaScript、React、Node、安全等方面,每天仅需 30 秒。

    • 精选常见面试题,帮助您准备下一次面试
    • 精选常见交互,帮助您拥有简洁酷炫的站点
    • 精选有用的 React 片段,帮助你获取最佳实践
    • 精选常见代码集,帮助您提高打码效率
    • 整理前端界的最新资讯,邀您一同探索新世界
    488 引用 • 384 回帖
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 370 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
Vanessa
我们终此一生,就是要摆脱他人的期待,找到真正的自己。 昆明