在 ReactJS 中创建动态 table 内容

Creating dynamic table of contents in ReactJS

我有一个组件代表一个页面,该页面有多个 SectionHeader 组件作为该页面的子组件。我想通过检查作为 SectionHeaders 的 Page 子项来动态创建 table 内容。

<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;

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

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;

给事物正确的结构很重要。我认为这更有意义,因为现在 parent 和 children 之间存在真正的关系。属于某个部分的 TextBlock 应位于该部分内。现在这并不能解决您的 table 内容问题,但这是一个开始。例如,现在 Page 的所有直接 children 都是 Sections,因此您可以用它做更多事情。

如果您想在运行时构建真正动态的 table 内容,您应该寻找另一个地方来存储您的内容。您现在正在将模板与内容混合在一起,这并不理想。 React 组件中的通信实际上只有一种方式(沿着树向下),因此尝试将数据从组件传回同级组件或 parent 并不容易,也不是一个好主意。查看 Flux 以了解有关数据应如何流动的更多信息。

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