javascript - 创建丰富的表单组件以向父组件公开值

标签 javascript reactjs

在使用 React.js 几天后,我编写了大部分表单,如下所示(如 official tutorial 中所示):

React.createClass({
  handleSubmit: function (event) {
    event.preventDefault();
    var value = React.findDOMNode(this.refs.text).value;
    // do something with the value
  },
  render: function () {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="text" ref="text" defaultValue="foo" />
        <input type="submit" value="Save"/>
      </form>
    );
  }
}

但是,我最近发现了这种方法的一个弱点,即我无法编写丰富的表单组件以用于由此类组件构建的表单,例如:

var RichInput = React.createClass({
  render: function() {
    return (
      <div className="someStyle">
        <input type="text" ref="text" defaultValue="foo" />
      </div>
    );
  }
}

React.createClass({
  handleSubmit: function (event) {
    event.preventDefault();
    var value = React.findDOMNode(this.refs.text).value;
    // do something with the value
  },
  render: function () {
    return (
      <form onSubmit={this.handleSubmit}>
        <RichInput />
        <input type="submit" value="Save"/>
      </form>
    );
  }
}

现在我想知道。查看可用资源后,我发现可以使用以下方法来克服此限制:

var RichInput = React.createClass({
  render: function() {
    return (
      <div className="someStyle">
        <input type="text" value="foo" onChange={this.props.callback} />
      </div>
    );
  }
}

React.createClass({
  handleSubmit: function (event) {
    event.preventDefault();
    var value = this.state.text
    // do something with the value
  },
  getInitialState() {
    return {text: 'foo'};
  }
  updateText: function(value) {
    this.setState({text: value});
  }
  render: function () {
    return (
      <form onSubmit={this.handleSubmit}>
        <RichInput callback={this.updateText} />
        <input type="submit" value="Save"/>
      </form>
    );
  }
}

这是编写模块化表单组件的规范解决方案吗?我想知道这对我来说确实是一个很大的开销。我需要编写额外的函数并且我需要使组件状态完整,这让我有点远离适应这个解决方案。另外,我想知道性能,因为我真的不需要在每次更改时更新值,而只在(并且在提交表单的情况下)更新值。

我发现的一种可能性是使用:

React.findDOMNode(this.refs.rich.refs.text);

假设 RichInput 定义了 ref="rich"。但话又说回来,React 的文档说 refs 不应被视为公共(public) API,不应在组件外部访问。

最佳答案

这就是我构建抽象 Input 组件的方式。我将它用于各种目的(每当我需要用户输入某些内容并且我想稍后处理该操作时)(带有一些 Bootstrap 样式的 ES6/7 示例):

import React, { PropTypes, Component } from 'react';

export default class Input extends Component {
  static propTypes = {
    placeholder: PropTypes.string,
    buttonText: PropTypes.string,
    onButtonClick: PropTypes.func
  }

  constructor() {
    super();

    this._handleClick = this._handleClick.bind(this);
    this._handleKeyUp = this._handleKeyUp.bind(this);
  }

  render() {
    return (
      <div className='Input'>
        <div className='input-group'>
          <input type='text' className='form-control' placeholder={this.props.placeholder}
                 ref='inputBox' onKeyUp={this._handleKeyUp}
          />
          <span className='input-group-btn'>
            <form onSubmit={this._handleClick}>
              <button className='btn btn-success' type='submit'>{this.props.buttonText}</button>
            </form>
          </span>
        </div>
      </div>
    );
  }

  _handleClick(e) {
    e.preventDefault();
    let value = this.refs.inputBox.getDOMNode().value;
    this.props.onButtonClick(value);
    value = null;
  }

  _handleKeyUp(e) {
    e.preventDefault();
    if (e.keyCode === 13) {
      this._handleClick(e);
    }
  }
}

然后在 Parent 组件中,您可以像这样初始化它:

<Input placeholder='Enter something'
       buttonText='Submit'
       onButtonClick={this._handleButtonClick}
/>

并处理 _handleButtonClick:

_handleMakeSearch(text) {
  console.log(text);
}

关于javascript - 创建丰富的表单组件以向父组件公开值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31161277/

相关文章:

javascript - PouchDb/CouchDb 中的递归删除?

javascript - 在一行代码中用扩展语法替换数组条目?

javascript - 统一触摸和点击事件

javascript - 单击鼠标悬停以应用样式

javascript - 在 .map() 函数中发送 Prop

javascript - 如何在 native react 中的对象属性字符串中给出行空间

reactjs - 使用 Webpack 在 Electron 项目中使用外部目录中的组件

javascript - 需要帮助来获取 css 'font-size' 的浮点值

javascript - 通过后端和前端之间共享 CASL 库进行用户授权

javascript - 为什么这个列表排序器会崩溃?