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

Som*_*azx 2 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 ...
Run Code Online (Sandbox Code Playgroud)

理想情况下我不得不单独的组件<form>,然后为每个单独的子组件<inputs>,在没有标签或标签<div className="form-group">,并<span className="input-group-addon">和能够插入到这些不同点在HTML文档中,并保持组件层次.

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

谢谢.

Mic*_*ley 6

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

我通常会首先编写我希望可以使用的标记/ JSX :

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>
  );
}
Run Code Online (Sandbox Code Playgroud)

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

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>
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

通过利用this.props.children,getDefaultProps扩展运算符(例如,将道具转移到新元素<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>
Run Code Online (Sandbox Code Playgroud)

如果您对描述表单的结构更感兴趣,然后让库自动创建元素,您可能会查看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'))
Run Code Online (Sandbox Code Playgroud)