受控組件是通過綁定事件的方式,及時獲取組件狀態的變化,適合即時的數據驗證
非受控組件是通過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"));
受控組件&非受控組件
如果在表單組件中,需要進行立即/動態數據驗證,使用受控組件,否則使用非受控組件