受控组件是通过绑定事件的方式,及时获取组件状态的变化,适合即时的数据验证
非受控组件是通过React.createRef
创建的引用来获取需要的元素(状态),灵活性更高,开发者可以在需要时随时调用
受控组件
const hobbiesData = [
{
name: "钢琴",
value: "piano",
},
{
name: "读书",
value: "read",
},
{
name: "游泳",
value: "swiming",
},
];
class App extends React.Component {
state = {
username: "",
sex: "meal",
isStudent: true,
hobbies: [],
};
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
handleStuChange(isStudent) {
this.setState({
isStudent,
});
}
handleHobbiesChange(e) {
console.log(111, e.target.value);
this.setState({
hobbies: [...this.state.hobbies, e.target.value],
});
}
submit() {
console.log(this.state);
}
reset() {
this.setState({
username: "",
sex: "meal",
});
}
render() {
const { username, sex, isStudent, hobbies } = this.state;
return (
<div>
<p>
<span>用户名:</span>
<input
type="text"
name="username"
value={username}
onChange={this.handleChange.bind(this)}
/>
</p>
<p>
<span>性别:</span>
<select
name="sex"
value={sex}
onChange={this.handleChange.bind(this)}
>
<option value="meal">男</option>
<option value="femeal">女</option>
</select>
</p>
<p>
<span>学生:</span>
<input
type="radio"
name="isStudent"
checked={isStudent}
onChange={this.handleStuChange.bind(this, true)}
/>
是|
<input
type="radio"
name="isStudent"
checked={!isStudent}
onChange={this.handleStuChange.bind(this, false)}
/>
否
</p>
<p>
<span>hobbys:</span>
{hobbiesData.map((item) => {
return (
<span key={item.value}>
<span key={item.value}>{item.name}</span>
<input
type="checkbox"
name="hobbies"
value={item.value}
checked={hobbies.includes(item.value)}
onChange={this.handleHobbiesChange.bind(this)}
/>
</span>
);
})}
</p>
<p>
<button onClick={this.submit.bind(this)}>submit</button>
<button onClick={() => this.reset()}>reset</button>
</p>
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector("#app"));
非受控组件
表单数据不受控于 state
,使用 React
ref
从 DOM
节点中获取表单数据的组件
class App extends React.Component {
constructor(props) {
super(props);
// 推荐使用:React.createRef()
this.usernameRef = React.createRef();
this.pwdRef = React.createRef();
this.genderRef = React.createRef();
this.fileRef = React.createRef();
}
handleChange(e) {
// refs 被弃用了
// console.log(this.refs.usernameRef.value);
this.setState({
// [e.target.name]: this.refs.usernameRef.value,
[e.target.name]: this.usernameRef,
});
}
submit(e) {
e.preventDefault();
console.log(this.usernameRef.current.value);
console.log(this.genderRef.current.value);
console.log(this.fileRef.current.value);
}
reset(e) {
e.preventDefault();
this.usernameRef.current.value = "";
}
render() {
return (
<div>
<p>
<span>用户名:</span>
<input
type="text"
name="username"
ref={this.usernameRef}
onChange={this.handleChange.bind(this)}
/>
</p>
<p>
{/*
form field 默认值
组件挂载完毕后更新,不会导致 DOM 的任何更新
*/}
<select defaultValue="male" ref={this.genderRef}>
<option value="male">男</option>
<option value="female">女</option>
</select>
</p>
<p>
<input type="file" ref={this.fileRef} />
</p>
<p>
<button onClick={this.submit.bind(this)}>submit</button>
<button onClick={(e) => this.reset(e)}>reset</button>
</p>
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector("#app"));
受控组件&非受控组件
如果在表单组件中,需要进行立即/动态数据验证,使用受控组件,否则使用非受控组件