在ReactJS中创建动态目录

时间:2015-05-10 19:56:05

标签: reactjs

我有一个代表一个Page的组件,其中有几个SectionHeader组件作为该页面的子组件。我想通过检查作为SectionHeaders的Page的子项来动态创建目录。

<Page>
  <TaleOfContents sections={this.props.children} />

  <SectionHeader title={"Section A"} />
  <TextBlock>
    <p> Text here. </p>
  </TextBlock>

  <SectionHeader title={"Section B"} />
  <TextBlock>
    <p> Text here. </p>
  </TextBlock>
</Page>

不幸的是,this.props.children未定义。有没有办法动态获取Page的这些子节点并在TableOfContents中呈现它们?

编辑:这是我的页面组件。它实际上只是将一堆其他组件绑定在一起的一种大型渲染方法。

/** @jsx React.DOM */

var React = require('react/addons');

// COMPONENTS
var TextBlock = require('../text_block.jsx');
var PaperHeader = require('../header_paper.jsx')
var SectionHeader = require('../header_section.jsx');
var TableOfContents = require('../table_of_contents.jsx');

var Page = React.createClass({

  render: function() {
    return (
      <div>
        <PaperHeader
        title={"Page Title"}
        authors={["Cole Gleason"]}
        />

      <SectionHeader
       title={'First Section'}
       size={'large'}
      />

      <TextBlock
      key={"text_first"}
      >
      <p>
       Text goes here.
      </p>
    </TextBlock>
   <this.props.activeRouteHandler/>
 </div>
 );
 }
});

 module.exports = Page;

1 个答案:

答案 0 :(得分:2)

您可以将内部组件放在一个数组中,迭代它们然后渲染它们。像这样:

var React = require('react/addons');

// COMPONENTS
var TextBlock = require('../text_block.jsx');
var PaperHeader = require('../header_paper.jsx')
var SectionHeader = require('../header_section.jsx');
var TableOfContents = require('../table_of_contents.jsx');

var Page = React.createClass({

  render: function() {
    var contents = [
      <PaperHeader title={"Page Title"} authors={["Cole Gleason"]} />,
      <SectionHeader title={'First Section'} size={'large'} />,
      <TextBlock key={"text_first"}>
        <p>
          Text goes here.
        </p>
      </TextBlock>,
      <this.props.activeRouteHandler/>
    ];

    var titles = contents.map(function(item) {
      if (item.title && some_other_requirement) {
        return item.title;
      }
      return undefined;
    });

    return (
      <div>
        <TOC titles={titles} />
        {contents}  
      </div>
    );
  }
});

module.exports = Page;

我不禁觉得你并没有真正以正确的理由和正确的方式使用React。您正在将React组件视为简单模板。这样的事情更有意义:

var React = require('react/addons');

// COMPONENTS
var Page = require('../Page.jsx');
var Section = require('../Section.jsx');
var TextBlock = require('../TextBlock.jsx');

var App = React.createClass({
  render: function() {
    return (
      <Page title='Page title'>
        <Section title='Section title'>
          <TextBlock>
            <p>Text goes here</p>
          </TextBlock>
          <TextBlock>
            <p>Text goes here</p>
          </TextBlock>
        </Section>
        <this.props.activeRouteHandler />
      </Page>
    );
  }
});

module.exports = App;

为事物提供正确的结构非常重要。我认为这更有意义,因为现在父母和孩子之间存在真正的关系。属于某个部分的TextBlock应位于该部分内。现在这不能解决您的目录问题,但这是一个开始。例如,现在Page的所有直接孩子都是Sections,这有助于您做到这一点。

如果要在运行时构建真实的动态目录,则应该查看另一个存储内容的位置。你现在正在将模板与内容混合在一起,这并不理想。 React组件中的通信实际上只是以一种方式(在树下),因此尝试将数据从组件传递回兄弟或父母并不容易也不是一个好主意。请查看Flux,了解有关数据应如何流动的更多信息。

另一个好读:https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0