🌈 受控组件
- 受控组件: 使用 1/2 的控制表单输入行为、取值方式的组件(简记:实时将表单数据更新到state中,想用的时候从state中取)
- 表单数据受控于 state
- 控制表单操作并且同步 state
- 非受控组件: 表单数据不受控于 state(简记:现用现取表单中的数据)
- checkbox、radio 写法
const hobbiesData = [
{
name: '钢琴',
value: 'piano'
},
{
name: '旅行',
value: 'travel'
},
{
name: '跑步',
value: 'running'
},
{
name: '唱歌',
value: 'singing'
}
]
class App extends React.Component {
state = {
username: '',
password: '',
intro: '',
gender: 'male',
isStudent: false,
hobbies: [],
hobbiesData
}
// handleUsernameChange(e) {
// this.setState({
// username: e.target.value
// }, () => {
// console.log(this.state.username);
// })
// }
// handlePasswordChange(e) {
// this.setState({
// password: e.target.value
// })
// }
// handleIntroChange(e) {
// this.setState({
// intro: e.target.value
// })
// }
handleChange(e) {
this.setState({
[e.target.name]: e.target.value
})
}
handleIsStudentChange(isStudent) {
this.setState({
isStudent
})
}
handleHobbiesChange(e) {
if (e.target.checked) {
this.setState({
hobbies: [...this.state.hobbies, e.target.value]
})
} else {
this.setState({
hobbies: this.state.hobbies.filter(v => v !== e.target.value)
})
}
}
handleBtnClick(e) {
e.preventDefault();
const { username, password, intro, gender, isStudent, hobbies } = this.state;
console.log(username, password, intro, gender, isStudent, hobbies);
}
handleResetClick(e) {
e.preventDefault();
this.setState({
username: '',
password: '',
intro: '',
gender: 'male',
isStudent: false,
hobbies: []
})
}
render() {
const { username, password, intro, gender, isStudent, hobbies, hobbiesData } = this.state;
return (
<form>
<p>
用户名:
{/* state就是表单的唯一数据源 */}
<input type="text" placeholder="请输入用户名"
value={ username }
name="username"
onChange={ this.handleChange.bind(this) }
/>
</p>
<p>
密码:
<input type="password" placeholder="请输入密码"
value={ password }
name="password"
onChange={ this.handleChange.bind(this) }
/>
</p>
<p>
介绍:
<textarea
value={ intro }
name="intro"
onChange={ this.handleChange.bind(this) }
/>
</p>
<p>
性别: <select
value={ gender }
name="gender"
onChange={ this.handleChange.bind(this) }
>
<option value="male">男</option>
<option value="female">女</option>
</select>
</p>
<p>
学生:
<input type="radio" name="isStudent" checked={ isStudent } onChange={ this.handleIsStudentChange.bind(this, true) } />是
<input type="radio" name="isStudent" checked={ !isStudent } onChange={ this.handleIsStudentChange.bind(this, false) } />否
</p>
{/* <p>
爱好:
<input type="checkbox" name="hobbies" value="piano" checked={ hobbies.includes('piano') } onChange={ this.handleHobbiesChange.bind(this) } />钢琴
<input type="checkbox" name="hobbies" value="travel" checked={ hobbies.includes('travel') } onChange={ this.handleHobbiesChange.bind(this) } />旅行
<input type="checkbox" name="hobbies" value="running" checked={ hobbies.includes('running') } onChange={ this.handleHobbiesChange.bind(this) } />跑步
<input type="checkbox" name="hobbies" value="singing" checked={ hobbies.includes('singing') } onChange={ this.handleHobbiesChange.bind(this) } />唱歌
</p> */}
<p>
爱好:
{
hobbiesData.map(item => {
return (
<span key={ item.value }>
<input type="checkbox" name="hobbies"
value={ item.value }
checked={ hobbies.includes(item.value) }
onChange={ this.handleHobbiesChange.bind(this) } />{ item.name }
</span>
)
})
}
</p>
<button onClick={ this.handleBtnClick.bind(this) }>Login</button>
<button onClick={ this.handleResetClick.bind(this) }>Reset</button>
</form>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'));
非受控组件
- 表单数据不受控于 state,使用 React ref 从 DOM 节点中获取表单数据的组件
select
、 input:checkbox
、 input:radio
等类型,得用 defaultValue
、 defaultChecked
赋默认值
方法一
- 元素上直接
ref="xxxRef"
- JS 中通过
this.refs.xxxRef
访问
- 获取值通过
this.refs.xxxRef.value
方法二(hooks)
constructor
中 this.xxxRef = React.createRef()
- 元素上
ref={ this.xxxRef }
- JS 中通过
this.xxxRef.current.value
获取值
class App extends React.Component {
constructor(props) {
super(props);
this.usernameRef = React.createRef();
this.passwordRef = React.createRef();
this.genderRef = React.createRef();
this.fileRef = React.createRef();
this.handleSubmitClick = this.handleSubmitClick.bind(this);
this.handleResetClick = this.handleResetClick.bind(this);
}
handleSubmitClick(e) {
e.preventDefault();
// const username = this.refs.usernameRef.value;
// const password = this.refs.passwordRef.value;
const username = this.usernameRef.current.value;
const password = this.passwordRef.current.value;
const gender = this.genderRef.current.value;
const file = this.fileRef.current.files[0];
console.log(username, password, gender, file);
}
handleResetClick(e) {
e.preventDefault();
// this.refs.usernameRef.value = '';
// this.refs.passwordRef.value = '';
this.usernameRef.current.value = '';
this.passwordRef.current.value = '';
this.genderRef.current.value = 'male';
}
render() {
return (
<form onSubmit={ this.handleSubmitClick }>
<p>
用户名:
{/* <input type="text" placeholder="请输入用户名" ref="usernameRef" /> */}
<input type="text" placeholder="请输入用户名" ref={ this.usernameRef } />
</p>
<p>
密码:
{/* <input type="password" placeholder="请输入密码" ref="passwordRef" /> */}
<input type="password" placeholder="请输入密码" ref={ this.passwordRef } />
</p>
<p>
性别:
<select
// form field 的默认值 -> 组件挂载完毕后进行更新的值,不会导致DOM的任何更新
defaultValue="male"
ref={ this.genderRef }
>
<option value="male">男</option>
<option value="female">女</option>
</select>
</p>
<p>
上传:
<input type="file" ref={ this.fileRef } />
</p>
<p>
学生:
<input type="radio" name="isStudent" defaultChecked={ true } />是
<input type="radio" name="isStudent" defaultChecked={ false } />否
</p>
<p>
爱好:
<input type="checkbox" name="hobbies" value="piano" defaultChecked={ true } />钢琴
<input type="checkbox" name="hobbies" value="travel" defaultChecked={ false } />旅行
<input type="checkbox" name="hobbies" value="running" defaultChecked={ false } />跑步
<input type="checkbox" name="hobbies" value="singing" defaultChecked={ true } />唱歌
</p>
<p>
{/* <button onClick={ this.handleSubmitClick }>登录</button> */}
<button type="submit">登录</button>
<button onClick={ this.handleResetClick }>重置</button>
</p>
</form>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'));