渲染React嵌套组件

时间:2016-12-06 01:42:27

标签: reactjs

有没有办法在不同的div下呈现React组件的子项?

<Page>
   <Header> ... </Header>
   <Content> ... </Content>
   <Actions> ... </Actions>
</Page>

<div class="page">
   <div class="header-wrapper>
      <div class="header"> ... </div>
   </div>
   <div class="content-wrapper">
      <div class="content"> ... </div>
      <div class="actions"> ... </div>
   </div>
</div>

这里我需要包装器,因为标头的布局与内容和操作所在的区域不同。

显而易见的解决方案可能是引入一个Body组件,但是有一种更优雅的方式来抽象具体的div树,它需要从Page声明的逻辑组件(Header,Content,Actions)表示某个布局。

另一个有效的解决方案是将Header,Content和Actions作为React文档中建议的属性传递:

<Page
   header={
      <Header> ... </Header>
   }
   content={
      <Content> ... </Content>
   }
   actions={
      <Actions> ... </Actions>
   }
/>

谢谢, 乔治

3 个答案:

答案 0 :(得分:0)

React让您访问个别孩子

<Page>
   <Header> ... </Header>
   <Content> ... </Content>
   <Actions> ... </Actions>
</Page>

内部<Page />组件渲染

render() {
  // when multiple elements are passed children prop is an array.
  // extract each of the element passed from the array and place them     
  // wherever needed in the JSX
  const [HeaderView, ContentView, ActionsView] = this.props.children;

  <div class="page">
    <div class="header-wrapper>
      {HeaderView}
    </div>
    <div class="content-wrapper">
      {ContentView}
      {ActionsView}
    </div>
  </div>
}

答案 1 :(得分:0)

使用React.Children.toArray将您的props.children(这是一个不透明的数据结构)转换为数组并安全地重新组织它们。

转换为数组后,您可以使用findforEach方法获取每个方法 - 标题,内容和操作 - 通过测试项目的类型。

const children = React.Children.toArray(this.props.children);
const headerView = children.find(child => child.type.name === 'HeaderView');
const contentView = children.find(child => child.type.name === 'ContentView');
const actionsView = children.find(child => child.type.name === 'ActionsView');

<div class="page">
  <div class="header-wrapper>
    {headerView}
  </div>
  <div class="content-wrapper">
    {contentView}
    {actionsView}
  </div>
</div>

请记住使用类或函数声明声明HeaderView,ContentView和ActionsView,而不是匿名函数,如:

const HeaderView = props => {
  // some stateless rendering
};

否则他们可能没有type.name来测试。

答案 2 :(得分:0)

在Aurelia中,你可以使用命名的插槽来实现这个结果,但是我发现最好的解决方法是做到这一点:

// ...

const header = <Header someProp={someVal} />;
const content = <Content someOtherProp={someOtherVal} />;
const actions = <Actions action1={someAction} action2={someOtherAction} />;

return (
  <Page header={header} content={content} actions={actions} />
);

和page.jsx:

import React from 'react';
import PropTypes from 'prop-types';

export const Page = ({ header, content, actions }) => (
  <div className="page">
    <div className="header-wrapper">
      <div className="header">
        {header}
      </div>
    </div>
    <div className="content-wrapper">
      <div className="content">
        {content}
      </div>
      <div className="actions">
        {actions}
      </div>
    </div>
  </div>
);

Page.propTypes = {
  header: PropTypes.node.isRequired,
  content: PropTypes.node.isRequired,
  actions: PropTypes.node.isRequired,
};