【React入门学习】10.表单

100 阅读2分钟

表单

参考文档:react.docschina.org/docs/forms.…

在 React 里,HTML 表单元素的工作方式和其他的 DOM 元素有些不同,这是因为表单元素通常会保持一些内部的 state。例如这个纯 HTML 表单只接受一个名称:

<form>
  <label>
    名字:
    <input type="text" name="name" />
  </label>
  <input type="submit" value="提交" />
</form>

此表单具有默认的 HTML 表单行为,即在用户提交表单后浏览到新页面。如果你在 React 中执行相同的代码,它依然有效。但大多数情况下,使用 JavaScript 函数可以很方便的处理表单的提交, 同时还可以访问用户填写的表单数据。实现这种效果的标准方式是使用“受控组件”。

受控组件

在 HTML 中,表单元素(如<input>、 <textarea> 和 <select>)之类的表单元素通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。

我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。

image.png

 class NameForm extends React.Component{
            constructor(props) {
                super(props);
                this.state = { value: '' };

                this.handleChange = this.handleChange.bind(this);
                this.handleSubmit = this.handleSubmit.bind(this);
            }
            handleChange(event) {
                this.setState({ value: event.target.value });
            }
            handleSubmit(event) {
                alert('提交的名字' + this.state.value);
                event.preventDefault();
            }
            render() {
                return (
                    <form onSubmit={this.handleSubmit}>
                        <label>
                            名字:
                            <input type="text" value={this.state.value} onChange={this.handleChange} />
                        </label>
                        <input type="submit" value="提交" />
                    </form>
                )
            }
        }
        ReactDOM.render(
            <NameForm />,
            document.getElementById('root')
        )

textarea 标签

在 HTML 中, <textarea> 元素通过其子元素定义其文本:

<textarea>
  你好, 这是在 text area 里的文本
</textarea>

而在 React 中,<textarea> 使用 value 属性代替。这样,可以使得使用 <textarea> 的表单和使用单行 input 的表单非常类似:

class EssayForm extends React.Component{
            constructor(props){
                super(props);
                this.state={
                    value:'请撰写一篇关于你喜欢的 DOM 元素的文章.'
                };
                this.handleChange = this.handleChange.bind(this);
                this.handleSubmit = this.handleSubmit.bind(this)
            }
            handleChange(event){
                this.setState({value:event.target.value})
            }
            handleSubmit(event){
                alert('提交的文章:'+ this.state.value);
                event.preventDefault();
            }
            render(){
                return(
                    <form onSubmit={this.handleSubmit}>
                        <label>
                            文章:
                            <textarea value={this.state.value} onChange={this.handleChange}></textarea>
                        </label>
                        <input type="submit" value="提交" />
                    </form>
                )
            }
        }
        ReactDOM.render(
            <EssayForm />,
            document.getElementById('root2')
        )

select 标签

请注意,由于 selected 属性的缘故,椰子选项默认被选中。React 并不会使用 selected 属性,而是在根 select 标签上使用 value 属性。这在受控组件中更便捷,因为您只需要在根标签中更新它。例如:

class FlavorForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 'coconut'};
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {    this.setState({value: event.target.value});  }
  handleSubmit(event) {
    alert('你喜欢的风味是: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          选择你喜欢的风味:
          <select value={this.state.value} onChange={this.handleChange}>            <option value="grapefruit">葡萄柚</option>
            <option value="lime">酸橙</option>
            <option value="coconut">椰子</option>
            <option value="mango">芒果</option>
          </select>
        </label>
        <input type="submit" value="提交" />
      </form>
    );
  }
}

image.png

文件 input 标签

处理多个输入 当需要处理多个 input 元素时,我们可以给每个元素添加 name 属性,并让处理函数根据 event.target.name 的值选择要执行的操作。

class Reservation extends React.Component{
            constructor(props) {
                super(props);
                this.state = {
                    isGoing: true,
                    numberOfGuests: 2
                };
                this.handleInputChange = this.handleInputChange.bind(this);
            }
            handleInputChange(event) {
                const target = event.target;
                const value = target.name === 'isGoing' ? target.checked : target.value;
                const name = target.name;

                /*
                    es6语法 等同于下面的内容
                    var partialState = {};
                    partialState[name] = value;
                    this.setState(partialState);
                */
                this.setState({
                    [name]: value
                });
            }

            render() {
                return (
                    <form>
                        <label>
                            参与:
                            <input
                                name="isGoing"
                                type="checkbox"
                                checked={this.state.isGoing}
                                onChange={this.handleInputChange}
                            />
                        </label>
                        <br />
                        <label>
                            来宾人数:
                            <input 
                                name="numberOfGuests"
                                type="number"
                                value={this.state.numberOfGuests}
                                onChange={this.handleInputChange} />
                        </label>
                    </form>
                )
            }
        }
        ReactDOM.render(
            <Reservation />,
            document.getElementById('root4')
        )

image.png