通过学习《第一个组件》这一节,相信你已经理解了 props 和 state 的区别。这一节,我们会介绍 “受控组件”和“非受控组件”这两个概念。
非受控组件
我们首先看一个简单的例子,现在有一个输入组件。
const MyInput = ({ onChange }) => (
);
上面这个组件会显示一个输入框,每次有用户输入,就会调用传入的参数 onChange。
然后,将这个组件放入Home组件中(app/home/index.js)。
const MyInput = ({ onChange }) => (
<input onChange={onChange} />
);
export default class Home extends React.Component {
onTextChange = (event) => {
console.log(event.target.value);
}
render() {
return (
<MyInput onChange={this.onTextChange} />
);
}
}
上面代码中,我们将 MyInput 组件与一个监听函数 onTextChange 封装在一起。
现在,需要一个重置按钮,点击后可以清空 MyInput 的内容,那么可以像下面这样调整。
<div>
<MyInput onChange={this.onChange} />
<button onClick={this.onTextReset}>Reset</button>
</div>
onTextReset = () => {
// 我该怎么做?
// 拿到 MyInput 内部的 input 元素然后设置 value 为 ''?
}
看起来,修改 MyInput 中的值不太容易。
对于这种不能直接控制状态的组件,我们称之为“非受控组件”。
受控组件
接着,我们做一些调整。将其改造成受控组件。
const MyInput = ({ value = '', onChange }) => (
<input value={value} onChange={onChange} />
);
这时, MyInput 的输入完全由 value 属性来决定。
你会发现,新的代码你无法在输入框输入任何东西(因为 value 总是 ‘’)。
我们改造一下 Demo,让它可以重新工作:
import React from 'react';
const MyInput = ({ value = '', onChange }) => (
<input value={value} onChange={onChange} />
);
export default class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
text: '',
};
}
onTextChange = (event) => {
this.setState({ text: event.target.value });
}
render() {
return (
<MyInput value={this.state.text} onChange={this.onTextChange} />
);
}
}
好了,重置变得轻而易举:
onTextReset = () => {
this.setState({ text: '' });
}
“受控”与“非受控”两个概念,区别在于这个组件的状态是否可以被外部修改。一个设计得当的组件应该同时支持“受控”与“非受控”两种形式,即当开发者不控制组件属性时,组件自己管理状态,而当开发者控制组件属性时,组件该由属性控制。而开发一个复杂组件更需要注意这点,以避免只有部分属性受控,使其变成一个半受控组件。