如何减少reactjs / JSX中的标记量

时间:2014-12-06 22:31:10

标签: reactjs

我想清理我的JSX,将表示标记与功能标记/ DOM元素分开。

我有一个表单,它将成为我的组件层次结构的顶层。在下面将有几个输入和表单元素来构成完整的组件层次结构。还有相当数量的twitter bootstrap“cruft”主要用于控制演示。

例如:

render: function() {
  return (
    <form role="form" className="form-horizontal">
      <div className="form-group">
        <label htmlFor="homePrice">Home Price</label>
        <div className="input-group input-group-lg">
          <span className="input-group-addon">$</span>
          <input id="homePrice"
            className="form-control"
            onChange={this.priceChange}
            value={this.state.homePrice}
          />
        </div>
      </div>
      <div className="form-group">
        <label htmlFor="depositAmount">Deposit Amount</label>
        <div className="input-group input-group-lg">
          <span className="input-group-addon">$</span>
          <input id="depositAmount"
            className="form-control"
            onChange={this.depositChange}
            value={this.state.depositAmount}
          />
        </div>
      </div>
      ... snip ...

理想情况下,我会为<form>创建单独的组件,然后为每个<inputs>创建单独的子组件,而不使用标签标记或<div className="form-group"><span className="input-group-addon">并且能够将它们插入HTML文档中的各个点并维护组件层次结构。

那么我该如何实现这一点并维护组件层次结构。更改输入中的值会影响父级最顶层组件中的状态。

感谢。

1 个答案:

答案 0 :(得分:6)

你可以通过作曲非常有效地做到这一点。您希望自定义组件的自定义程度取决于您;通过更多道具和条件逻辑,您可以获得更多可自定义性。

我经常会先编写我可以使用的标记/ JSX wish

render: function() {
  return (
    <Form horizontal>
      <Input id="homePrice"
             addon="$" label="Home Price"
             onChange={this.priceChange}
             value={this.state.homePrice} />
      <Input id="depositAmount"
             addon="$" label="Deposit Amount"
             onChange={this.depositChange}
             value={this.state.depositAmount} />
    </Form>
  );
}

然后,您可以根据需要开始实施组件以使其工作:

var Form = React.createClass({
  render: function() {
    var direction = "vertical";
    if (this.props.horizontal) direction="horizontal";

    return (
      <form role="form" className={"form-" + direction}
            onSubmit={this.props.onSubmit}>
        {this.props.children}
      </form>
    );
  }
});

var Input = React.createClass({
  render: function() {
    return (
      <div className="form-group">
        <label htmlFor={this.props.id}>{this.props.label}</label>
        <div className="input-group input-group-lg">
          <span className="input-group-addon">{this.props.addon}</span>
          <input id={this.props.id}
                 className="form-control"
                 onChange={this.props.onChange}
                 value={this.props.value} />
        </div>
      </div>
    );
  }
});

通过利用this.props.childrengetDefaultProps,扩展运算符(例如,通过<someElement {...this.props} />将道具转移到新元素)和条件,您可以为更复杂的组件创建非常好的抽象。此外,propTypes允许您指定组件所具有的属性,作为文档以及在开发中捕获运行时错误的方法。

您可以考虑查看React Bootstrap的源代码,了解它们如何实现复合组件以包装更复杂的Bootstrap HTML;例如,这是您使用选项卡组件编写的内容:

<TabbedArea defaultActiveKey={2}>
  <TabPane eventKey={1} tab="Tab 1">TabPane 1 content</TabPane>
  <TabPane eventKey={2} tab="Tab 2">TabPane 2 content</TabPane>
</TabbedArea>

如果您对描述表单的结构更感兴趣,然后让库自动创建元素,您可能会查看React Forms之类的项目:

function Person(props) {
  props = props || {}
  return (
    <Schema name={props.name} label={props.label}>
      <Property name="first" label="First name" />
      <Property name="last" label="Last name" />
    </Schema>
  )
}

var family = (
  <Schema>
    <Person name="mother" label="Mother" />
    <Person name="father" label="Father" />
    <List name="children" label="Children">
      <Person />
    </List>
  </Schema>
)

React.renderComponent(
  <Form schema={family} />,
  document.getElementById('example'))