学习React系列(四)——受控组件与非受控组件

2023-04-27,,

受控组件:通过组件的状态与属性的改变来控制组件

不可控组件:直接通过底层的dom来控制组件(具体来说就是通过绑定再底层dom上的方法来实现的,比如说ref,onChange)

受控组件

function validate(name, email, password) {
// we are going to store errors for all fields
// in a signle array
const errors = []; if (name.length === 0) {
errors.push("Name can't be empty");
} if (email.length < 5) {
errors.push("Email should be at least 5 charcters long");
}
if (email.split('').filter(x => x === '@').length !== 1) {
errors.push("Email should contain a @");
}
if (email.indexOf('.') === -1) {
errors.push("Email should contain at least one dot");
} if (password.length < 6) {
errors.push("Password should be at least 6 characters long");
} return errors;
} class SignUpForm extends React.Component {
constructor() {
super();
this.state = {
name: '',
email: '',
password: '', errors: [],
}; this.handleSubmit = this.handleSubmit.bind(this);
} handleSubmit(e) {
e.preventDefault(); const { name, email, password } = this.state; const errors = validate(name, email, password);
if (errors.length > 0) {
this.setState({ errors });
return;
} // submit the data...
} render() {
const { errors } = this.state;
return (
<form onSubmit={this.handleSubmit}>
{errors.map(error => (
<p key={error}>Error: {error}</p>
))}
<input
value={this.state.name}
onChange={evt => this.setState({ name: evt.target.value })}
type="text"
placeholder="Name"
/>
<input
value={this.state.email}
onChange={evt => this.setState({ email: evt.target.value })}
type="text"
placeholder="Email"
/>
<input
value={this.state.password}
onChange={evt => this.setState({ password: evt.target.value })}
type="password"
placeholder="Password"
/> <button type="submit">Submit</button>
</form>
);
}
} ReactDOM.render(<SignUpForm />, document.body);

不可控组件

function validate(name, email, password) {
// we are going to store errors for all fields
// in a signle array
const errors = []; if (name.length === 0) {
errors.push("Name can't be empty");
} if (email.length < 5) {
errors.push("Email should be at least 5 charcters long");
}
if (email.split('').filter(x => x === '@').length !== 1) {
errors.push("Email should contain a @");
}
if (email.indexOf('.') === -1) {
errors.push("Email should contain at least one dot");
} if (password.length < 6) {
errors.push("Password should be at least 6 characters long");
} return errors;
} class SignUpForm extends React.Component {
constructor() {
super();
this.state = {
errors: [],
}; this.handleSubmit = this.handleSubmit.bind(this);
} handleSubmit(e) {
e.preventDefault(); const name = ReactDOM.findDOMNode(this._nameInput).value;
const email = ReactDOM.findDOMNode(this._emailInput).value;
const password = ReactDOM.findDOMNode(this._passwordInput).value; const errors = validate(name, email, password);
if (errors.length > 0) {
this.setState({ errors });
return;
} // submit the data...
} render() {
const { errors } = this.state;
return (
<form onSubmit={this.handleSubmit}>
{errors.map(error => (
<p key={error}>Error: {error}</p>
))}
<input
ref={nameInput => this._nameInput = nameInput}
type="text"
placeholder="Name"
/>
<input
ref={emailInput => this._emailInput = emailInput}
type="text"
placeholder="Email"
/>
<input
ref={passwordInput => this._passwordInput = passwordInput}
type="password"
placeholder="Password"
/> <button type="submit">Submit</button>
</form>
);
}
} ReactDOM.render(<SignUpForm />, document.body);

在使用非受控组件的时候可以通过设置默认值来对dom的value进行初始化操作

class NameForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
} handleSubmit(event) {
alert('A name was submitted: ' + this.input.value);
event.preventDefault();
} render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input
defaultValue="Bob"
type="text"
ref={(input) => this.input = input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}

另外, <input type="checkbox"> 和 <input type="radio"> 支持 defaultChecked<select> 和<textarea> 支持 defaultValue.

访问文件的实例(非控制组件)

class FileInput extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
alert(
`Selected file - ${this.fileInput.files[0].name}`
);
} render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Upload file:
<input
type="file"
ref={input => {
this.fileInput = input;
}}
/>
</label>
<br />
<button type="submit">Submit</button>
</form>
);
}
} ReactDOM.render(
<FileInput />,
document.getElementById('root')
);

他们的应用场景对比:

结论:尽可能的使用受控组件来进行表单提交的操作,除非符合本文中给出的不可控例子或者为单次提交检验的form操作。(不可控实现的原理其实就是在ref的回掉中把当前的dom对象赋给组件的某个属性,通过该属性进而操作dom对象)

参考:https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/

https://reactjs.org/docs/uncontrolled-components.html

学习React系列(四)——受控组件与非受控组件的相关教程结束。

《学习React系列(四)——受控组件与非受控组件.doc》

下载本文的Word格式文档,以方便收藏与打印。