如何最好地创建选项卡式内容组件,文件夹,方法结构

时间:2018-10-20 10:38:29

标签: javascript reactjs components styled-components

我正在尝试构建选项卡式内容组件,但不确定如何最好地进行此操作。

我有一个下面的对象数组,可以接受任意数量

tabs= {[
  {
    "title": "Some title 1",
    "otherComponents": [
      <Title ... />,
      <Paragraph... />
    ]
  },
    ...
    ...
    ...
}]

我觉得我首先需要集中精力显示tab.title,然后在otherComponents中显示tab.contents。但不确定如何将两者链接在一起以标识活动选项卡以及要显示的内容。在此组件的文件夹结构以及需要使用哪种功能方面的任何帮助将不胜感激。我不确定采用最佳方法。您建议首先关注什么?

我猜猜下面的函数:getTabHeadersgetTabContents,然后将它们显示在下面?

我在下面具有以下文件夹结构

-tabbed-content      -tabbed-content.js      -tab-content.js      -tab-headers

不确定它们是否都应放入主文件tabbed-content

tabbed-content中,我有类似以下内容

  getTabbedContent() {
    const {
    tabs,
  } = this.props;

  const numberOfTabs = Object.keys(tabs).length;

  return (
    <StyledTabbedContent>
      { tabs.map((tab, index) => (
        <TabHeader
          key={uuidv1()}
          title={tab.title}
          tabNumber={1+ index}
          numberOfTabs={numberOfTabs}
        />
        ),
      )}
    </StyledTabbedContent>
  );
  }

tab-header中,我有以下

  render() {
    const { numberOfTabs, title } = this.props;
    return (
      <StyledTab 
        numberOfTabs={numberOfTabs}
      >
          <StyledTitle>{title}</StyledTitle>
      </StyledTab>     
    ) 
  }
}

我认为tab-content中存在与上面类似的内容,但是不确定如何将它们两者链接在一起……这使我觉得我走错了道路……这就是为什么我要一个文件夹结构/方法结构或一个首先要解决该问题的计划的原因

1 个答案:

答案 0 :(得分:1)

我建议您创建一个更通用的Tabbar组件。在您的应用中,您可能需要执行以下操作:

<TabbedContent>
  <div label="Tab 1"> ... individual content goes here ... </div>
  <div label="Tab 2"> ... individual content goes here ... </div>
  <div label="Tab 3"> ... individual content goes here ... </div>
</TabbedContent>

然后TabbedContent组件负责其余的工作:

  1. 剖析孩子
  2. 从标签属性创建标签
  3. 处理点击逻辑
  4. 是的,您可以使用样式组件

在此示例中,我将不使用react Refs,而是使用.bind进行修改。因此,请您自己修复此问题;)这只是为了向正确的方向推进。如果您的版本没有.bind,则可以更新我的帖子:)

您的TabbedContent组件应如下所示:

export default class TabbedContent extends Component {
  constructor(props) {
    super(props)

    // get the label from the first child
    const { children } = this.props
    const firstChild = children && children[0] 

    if (firstChild){
      // save active label in state
      const { label } = firstChild.props
      this.state = { activeTab: label }
    }

  }

}

TabbedContent的render方法应返回以下内容:

const {
  onClickTabItem,
  props: { children },
  state: { activeTab },
} = this

return (
<Tabs>
  <TabList>
    {children.map((child) => {
      const { label } = child.props
      return (
        <Tab
          active={label === activeTab}
          key={label}
          onClick={onClickTabItem.bind(this, label)}
        >
          {label}
        </Tab>
      )
    })}
  </TabList>
  <TabContent>
    {children.map((child) => {
      if (child.props.label !== activeTab) return undefined
      return child.props.children
    })}
  </TabContent>
</Tabs>
)

在调用该组件时将onClickTabItem方法添加到该组件并设置状态:

onClickTabItem = (tab) => {
  this.setState({ activeTab: tab })
}

您的Tab样式组件应实现属性active的行为:

${props => props.active && css`
  background: black;
  color: white;
`}