react系列知识---08表单

216 阅读4分钟

应用表单组件

  1. 文本框
import React, { Component } from 'react';
class App extends Component {
    constructor(props) {
        super(props);
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleTextareaChange = this.handleTextareaChange.bind(this);
        this.state = {
            inputValue: '',
            textareaValue: '',
        };
    }
    handleInputChange(e) {
        this.setState({
            inputValue: e.target.value,
        });
    }
    handleTextareaChange(e) {
        this.setState({
            textareaValue: e.target.value,
        });
    }
    render() {
        const { inputValue, textareaValue } = this.state;
        return (
            <div>
                <p>单行输入框:<input type="text" value={inputValue}
                    onChange={this.handleInputChange} /></p>
                <p>多行输入框:<textarea value={textareaValue}
                    onChange={this.handleTextareaChange} /></p>
            </div>
        );
    }
}
  1. 单选按钮与复选框
  • 单选框
import React, { Component } from 'react';
class App extends Component {
    constructor(props) {
        super(props);
        this.handeChange = this
            .handleChange
            .bind(this);
        this.state = {
            radioValue: ''
        };
    }
    handleChange(e) {
        this.setState({ radioValue: e.target.value });
    }
    render() {
        const { radioValue } = this.state;
        return (
            <div>
                <p>gender:</p>
                <label>
                    male:
                    <input
                        type="radio"
                        value="male"
                        checked={radioValue === 'male'}
                        onChange={this.handleChange} />
                </label>
                <label>
                    female:
                    <input
                        type="radio"
                        value="female"
                        checked={radioValue === 'female'}
                        onChange={this.handleChange} />
                </label>
            </div>
        );
    }
}
  • 多选框
import React, {Component} from 'react';
class App extends Component {
    constructor(props) {
        super(props);
        this.handleChange = this
            .handleChange
            .bind(this);
        this.state = {
            coffee: []
        };
    }
    handleChange(e) {
        const {checked, value} = e.target;
        let {coffee} = this.state;
        if (checked && coffee.indexOf(value) === -1) {
            coffee.push(value);
        } else {
            coffee = coffee.filter(i => i !== value);
        }
        this.setState({coffee});
    }
    render() {
        const {coffee} = this.state;
        return (
            <div>
                <p>请选择你最喜欢的咖啡:</p>
                <label>
                    <input
                        type="checkbox"
                        value="Cappuccino"
                        checked={coffee.indexOf('Cappuccino') !== -1}
                        onChange={this.handleChange}/>
                    Cappuccino
                </label>
                <br/>
                <label>
                    <input
                        type="checkbox"
                        value="CafeMocha"
                        checked={coffee.indexOf('CafeMocha') !== -1}
                        onChange={this.handleChange}/>
                    CafeMocha
                </label>
                <br/>
                <label>
                    <input
                        type="checkbox"
                        value="CaffeLatte"
                        checked={coffee.indexOf('CaffeLatte') !== -1}
                        onChange={this.handleChange}/>
                    Caffè Latte
                </label>
                <br/>
                <label>
                    <input
                        type="checkbox"
                        value="Machiatto"
                        checked={coffee.indexOf('Machiatto') !== -1}
                        onChange={this.handleChange}/>
                    Machiatto
                </label>
            </div>
        );
    }
}
  1. Select 组件
  • 单选
import React, {Component} from 'react';
class App extends Component {
    constructor(props) {
        super(props);
        this.handleChange = this
            .handleChange
            .bind(this);
        this.state = {
            area: ''
        };
    }
    handleChange(e) {
        this.setState({area: e.target.value});
    }
    render() {
        const {area} = this.state;
        return (
            <select value={area} onChange={this.handleChange}>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="hangzhou">杭州</option>
            </select>
        );
    }
}
  • 多选
import React, {Component} from 'react';
class App extends Component {
    constructor(props) {
        super(props);
        this.handleChange = this
            .handleChange
            .bind(this);
        this.state = {
            area: ['beijing', 'shanghai']
        };
    }
    handleChange(e) {
        const {options} = e.target;
        // 注意,这里返回的 options 是一个对象,并非数组
        const area = Object
            .keys(options)
            .filter(i => options[i].selected === true)
            .map(i => options[i].value);
        this.setState({area});
    }
    render() {
        const {area} = this.state;
        return (
            <select multiple={true} value={area} onChange={this.handleChange}>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="hangzhou">杭州</option>
            </select>
        );
    }
}

受控组件

总结下 React 受控组件更新 state 的流程:

  1. 可以通过在初始 state 中设置表单的默认值。
  2. 每当表单的值发生变化时,调用 onChange 事件处理器。
  3. 事件处理器通过合成事件对象 e 拿到改变后的状态,并更新应用的 state。
  4. setState 触发视图的重新渲染,完成表单组件值的更新。

在 React 中,数据是单向流动的。表单的数据源于组件的 state,并 通过 props 传入,这也称为单向数据绑定。然后,我们又通过 onChange 事件处理器将新的表单数 据写回到组件的 state,完成了双向数据绑定。

非受控组件

如果一个表单组件没有 value props(单选按钮和复选框对应的是 checked prop) 时,就可以称为非受控组件。相应地,你可以使用 defaultValue 和 defaultChecked prop 来表示 组件的默认状态。

对比受控组件和非受控组件

通过 defaultValue 或者 defaultChecked 来设置表单的默认值,它仅会被渲染 一次,在后续的渲染时并不起作用

面对比以下两个示例:

将输入的字母转化为大写展示:

<input
    value={this.state.value}
    onChange={e => {
        this.setState({ value: e.target.value.toUpperCase() })
    }}
/>

直接展示输入的字母:

<input
    defaultValue={this.state.value}
    onChange={e => {
        this.setState({ value: e.target.value.toUpperCase() })
    }}
/>

使用一个事件处理器来处理多个表单域

import React, {Component} from 'react';
class FormApp extends Component {
    constructor(props) {
        super(props);
        this.state = {
            name: '',
            age: 18
        };
    }
    handleChange(name, e) {
        const {value} = e.target;
        // 这里只能处理直接赋值这种简单的情况,复杂的处理建议使用 switch(name) 语句
        this.setState({[name]: value});
    }
    render() {
        const {name, age} = this.state;
        return (
            <div>
                <input
                    value={name}
                    onChange={this
                    .handleChange
                    .bind(this, 'name')}/>
                <input
                    value={age}
                    onChange={this
                    .handleChange
                    .bind(this, 'age')}/>
            </div>
        );
    }
}

表单组件的几个重要属性

  • 状态属性

    • value :类型为 text 的 input 组件、textarea 组件以及 select 组件都借助 value prop 来展示 应用的状态。
    • checked :类型为 radio 或 checkbox 的组件借助值为 boolean 类型的 selected prop 来展示 应用的状态。
    • selected :该属性可作用于 select 组件下面的 option 上,React 并不建议使用这种方式表 示状态,而推荐在 select 组件上使用 value 的方式。
  • 事件属性

刚刚提到的状态属性与事件属性存在一定的关联——在状态属性发生变化时,会触发 onChange 事件属性。同样,React 支持 DOM Level 3 中定义的所有表单事件。