六、表单

表单元素在React中自身维护一些状态,这些状态默认情况下是不受react控制的,这类状态不受react控制的表单元素称为非受控组件。

在React中,状态的修改必须通过组件的state,非受控组件有悖于这一原则,为了让表单元素的状态变更也能通过组件的state管理,React使用受控组件的技术达到这一目的。

1,受控组件

如果一个表单元素的值是由React来管理的,那么它就是一个受控组件。对于不同的表单元素,React的控制方法略有不同,常用的三类表单元素控制方式是:

①文本框

包含类型为text的input和textarea元素,它们受控的原理是:通过value属性设置表单元素的值,通过onChange时间监听值的变化,并将变化同步到React组件的state中:

class LoginForm extends Component {
    constructor() {
        this.state = {
            name: '',
            password: ''
        };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleChange(e) {
        const target = e.target;
        this.setState({
            [target.name]: target.value
        })
    }
    handleSubmit(e) {
        e.preventDefault();
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    用户名:
                    <input type="text" name="name" value={this.state.name} onChange={this.handleChange} />
                </label>
                <label>
                    密码:
                    <input type="password" name="name" value={this.state.password} onChange={this.handleChange} />
                </label>
                <input type="submit" value="登录" />
            </form>
        )
    }
}
export default LoginForm;

②列表

React通过在select上定义value属性来决定哪一个option处于选中状态。

class LoginForm extends Component {
    constructor() {
        this.state = {
            value: ''
        };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleChange(e) {
        const target = e.target;
        this.setState({
            value: target.value
        })
    }
    handleSubmit(e) {
        e.preventDefault();
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    列表:
                    <select value={this.state.value} onChange={this.handleChange}>
                        <option value="react">react</option>
                        <option value="redux">redux</option>
                    </select>
                </label>
                <input type="submit" value="登录" />
            </form>
        )
    }
}
export default LoginForm;

③复选框和单选框

React控制checked属性

class LoginForm extends Component {
    constructor() {
        this.state = {
            react: false,
            redux: false
        };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleChange(e) {
        const target = e.target;
        this.setState({
            [target.name]: target.checked
        })
    }
    handleSubmit(e) {
        e.preventDefault();
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    react:
                    <input type="checkbox" name="react" value="react" checked={this.state.react} onChange={this.handleChange} />
                </label>
                <label>
                    redux:
                    <input type="checkbox" name="redux" value="redux" checked={this.state.redux} onChange={this.handleChange} />
                </label>
                <input type="submit" value="登录" />
            </form>
        )
    }
}
export default LoginForm;

2,,非受控组件

表单元素的状态依然由表单元素自己管理,React提供了一个特殊的属性ref,用来引用React组件或DOM元素的实例。

class LoginForm extends Component {
    constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
    }
    handleSubmit(e) {
        console.log(this.input.value);
        e.preventDefault();
    }
    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    title:
                    <input type="text" ref={(input) => this.input = input} />
                </label>
                <input type="submit" value="登录" />
            </form>
        )
    }
}
export default LoginForm;

ref的值是一个函数,接收当前元素作为参数,上述例子中input参数指向的是当前元素,把input赋值给this.input,进而可以在组件的其他地方通过this.input获取这个元素。

使用非受控组件时,常常需要为相应的表单元素设置默认值,但无法通过value设置,因为React无法控制表单元素的value属性,一旦在非受控组件中定义了value属性的值,就很难保证后续表单元素的值的正确性。这种情况下,我们可以使用defaultValue属性指定默认值:

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <label>
                    title:
                    <input defaultValue="something" type="text" ref={(input) => this.input = input} />
                </label>
                <input type="submit" value="登录" />
            </form>
        )
    }

select元素和textarea元素也支持通过defaultValue设置默认值,checkbox和radio支持通过defaultChecked设置默认值。

非受控组件破坏了React对组件管理的一致性,往往容易出现不容易排查的问题,非特殊情况下,不使用。

posted on 2022-10-22 15:45  Zoie_ting  阅读(44)  评论(0编辑  收藏  举报