表单是前端很是重要的一块内容,而且每每包含了错误校验等逻辑。
React对表单元素作了专门的优化处理,他对表单元素作了一些抽象,使得他们的使用方式更统一更规范。javascript
表单里面出来了一个新的概念叫“约束性组件”。那么如何理解约束性组件和非约束性组件呢。html
约束性组件,简单的说,就是由React管理了它的value,而非约束性组件的value就是原生的DOM管理的。
他们的写法上也有很大区别。前端
<input type="text" defaultValue="a" />
这个 defaultValue 其实就是原生DOM中的 value 属性。这样写出的来的组件,其value值就是用户输入的内容,React彻底无论理输入的过程。java
<input type="text" value={this.state.name} onChange={this.handleChange} />
//...省略部分代码 handleChange: function(e) { this.setState({name: e.target.value}); }
这里,value属性再也不是一个写死的值,他是 this.state.name,而 this.state.name 是由 this.handleChange 负责管理的。
这个时候实际上 input 的 value 根本不是用户输入的内容。而是onChange 事件触发以后,因为 this.setState 致使了一次从新渲染。不过React会优化这个渲染过程,实际它依然是经过设置input的value来实现的。优化
可是必定要注意,约束性组件显示的值和用户输入的值虽然不少时候是相同的,但他们根本是两码事。约束性组件显示的是 this.state.name 的值。你能够在handleChange中对用户输入的值作任意的处理,好比你能够作错误校验。this
非约束性组件: 用户输入A -> input 中显示A
约束性组件: 用户输入A -> 触发onChange事件 -> handleChange 中设置 state.name = “A” -> 渲染input使他的value变成A
正式由于这样,强烈推荐使用约束性组件,由于它能更好的控制组件的生命流程。spa
React 把 input,textarea 和 select 三个组件作了抽象和封装,他们的用法变得很是统一,你基本上能够当作同一个组件来用。code
他们如今有统一的 value 属性 和 onChange 事件,如今对于这三种组件你均可以这样写orm
<input type='text' name='intro' id='intro' value={this.state.email} onChange={this.handleEmail} /> <textarea type='text' name='intro' id='intro' value={this.state.intro} onChange={this.handleIntro} /> <textarea type='text' name='intro' id='intro' value={this.state.intro} onChange={this.handleIntro} />
不过 chekbox有和上面三个不同,由于checkbox改变的不是 value ,而是 checked 状态。
你能够这样写:htm
<input type='radio' name='gender' checked={this.state.male} onChange={this.handleGender} value='MALE' /> <input type='radio' name='gender' checked={!this.state.male} onChange={this.handleGender} value='FEMALE' />
下面是一个包含了 input,textarea, select, radio 的表单,而且作了简单的校验:
var MyForm = React.createClass({ getInitialState: function() { return { email: "", intro: "", city: "hz", male: true, //性别 emailError: "", introError: "" }; }, handleEmail: function(e) { var value = e.target.value; var error = ''; if(!(/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(value))) { error = '请输入正确的Email'; } this.setState({ email: value, emailError: error }); }, handleIntro: function(e) { var value = e.target.value; var error = ""; if(value.length < 10) { error = "介绍不能少于十个字"; } this.setState({ intro: value, introError: error }); }, handleCity: function(e) { var value = e.target.value; this.setState({ city: value, }); }, handleGender: function(e) { var male = !!(e.target.value == 'MALE'); this.setState({ male: male }); }, render: function() { return ( <div> <p> <label htmlFor='email'>email:</label> <input type='text' name='intro' id='intro' value={this.state.email} onChange={this.handleEmail} /> <span>{this.state.emailError}</span> </p> <p> <label htmlFor='intro'>intro:</label> <textarea type='text' name='intro' id='intro' value={this.state.intro} onChange={this.handleIntro} /> <span>{this.state.introError}</span> </p> <p> <label htmlFor='city'>所在城市:</label> <select name='city' id='city' value={this.state.city} onChange={this.handleCity}> <option value='hz'>杭州</option> <option value='bj'>北京</option> <option value='sh'>上海</option> </select> </p> <p> <label>性别:</label> <input type='radio' name='gender' checked={this.state.male} onChange={this.handleGender} value='MALE' /> <input type='radio' name='gender' checked={!this.state.male} onChange={this.handleGender} value='FEMALE' /> </p> </div> ) } }); React.render( <MyForm />, document.getElementById("div1") );