受控组件
React 受控组件更新 state 的流程:
- 可以通过在初始 state 中设置表单的默认值。
- 每当表单的值发生变化时,调用 onChange 事件处理器。
- 事件处理器通过合成事件对象 e 拿到改变后的状态,并更新应用的 state。
- setState 触发视图的重新渲染,完成表单组件值的更新。
从示例中,我们能看出来表单的数据源于组件的 state,并通过 props 传入,这也称为单向数据绑定。然后,我们又通过 onChange 事件处理器将新的表单数据写回到组件的 state,完成了双向数据绑定。
非受控组件
import React, { Component } from 'react';
class Products extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
// 这里使用 React 提供的 ref prop 来操作 DOM
const { value } = this.refs.name;
console.log(value);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input ref="name" type="text" defaultValue="Hangzhou" />
<button type="submit">Submit</button>
</form>
);
}
}
export default Products;
图片展示:
如果一个表单组件没有 value props(单选按钮和复选框对应的是 checked prop)时,就可以称为非受控组件。相应地,你可以使用 defaultValue 和 defaultChecked prop 来表示组件的默认状态
非受控组件是一种反模式,它的值不受组件自身的 state 或 props 控制。通常,需要通过为其添加 ref prop 来访问渲染后的底层 DOM 元素。
受控组件和非受控组件的比较
- 性能问题
受控组件:每当表单数值发生变化,调用onChange事件处理器,损耗性能
非受控组件:不提倡使用 - 是否需要事件绑定
受控组件:为每个组件绑定一个 change 事件,并且定义一个事件处理器来同步表单值和组件的状态,这是一个必要条件,可使用一个事件处理器来处理多个表单域
import React, { Component } from 'react';
class Products 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>
);
}
}
export default Products;
表单组件的重要属性
- 状态属性
value:类型为 text 的 input 组件、textarea 组件以及 select 组件都借助 value prop 来展示应用的状态。
checked:类型为 radio 或 checkbox 的组件借助值为 boolean 类型的 selected prop 来展示应用的状态。
selected:该属性可作用于 select 组件下面的 option 上,React 并不建议使用这种方式表示状态,而推荐在 select 组件上使用 value 的方式。 - 事件属性
在状态属性发生变化时,会触发onChange 事件属性