学习React系列(四)——受控组件与非受控组件
受控组件:通过组件的状态与属性的改变来控制组件
不可控组件:直接通过底层的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/
学习React系列(四)——受控组件与非受控组件的更多相关文章
- React:受控组件与非受控组件混用实战 - 译文
原文链接:React: hybrid controlled components in action 受控组件 非受控组件 混用受控组件和非受控组件 原则一 原则二 原则三 原则四 实施方案 总结 F ...
- 浅谈react受控组件与非受控组件
引言 最近在使用蚂蚁金服出品的一条基于react的ant-design UI组件时遇到一个问题,编辑页面时input输入框会展示保存前的数据,但是是用defaultValue就是不起作用,输入框始终为 ...
- React受控组件和非受控组件
受控组件和非受控组件主要是用来解决表单组件状态谁来控制的问题.因为用户的输入会反应在界面上,相当于视图的状态发生了变化,而react是通过虚拟DOM比对修改视图的,这里就要决定谁来控制表单组件的状态. ...
- react 表单(受控组件和非受控组件)
我们知道表单元素与其他的普通DOM元素来说是不一样的,它们保存了自己的一些状态. 我们主要说的就是表单元素中的受控组件和非受控组件. 受控组件就是这个组件的状态是我们(react)控制的,这个组件的行 ...
- react中 受控组件和 非受控组件 浅析
一 受控组件 顾名思义,受控 也就是能够被控制,简而言之也就是 该组件ui的显示或者内部state逻辑的变化依赖外部的 props的传入. 二 非受控组件 顾名思义,非受控,也就是内部的视图变化,st ...
- react第十一单元(受控组件和非受控组件-实现类似于vue双向绑定的功能)
第十一单元(受控组件和非受控组件-实现类似于vue双向绑定的功能) #课程目标 理解因为react的单向数据流 理解表单组件会因为react数据流变的不好维护 理解受控组件与非受控组件的实质区别 理解 ...
- Vue父子组件及非父子组件如何通信
1.父组件传递数据给子组件 父组件数据如何传递给子组件呢?可以通过props属性来实现 父组件: 子组件通过props来接收数据: 方式1: 方式2 : 方式3: 这样呢,就实现了父组件向子组件传递数 ...
- React文档(十七)非受控组件
大多数情况下,我们建议使用受控组件(也就是用React的state来控制表单元素的value值)来实现表单.在一个受控组件里,表单数据被React组件处理.另一种方案就是非控制组件,这样的话表单数据就 ...
- React 受控组件和非受控组件
需求用户名自动获取 onChange用户状态发生改变 就获取值 就是时时获取值 使用onChange 点击按钮 获取密码 只要绑定了点击事件 就可以获取值 通过 let usercont=event. ...
随机推荐
- C语言的字符串操作函数小结
一.strcat()函数 char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾.它返回一个指向字符串de ...
- 不安装oracle客户端连接oracle数据库
PLSQL Developer 或Toad 不安装Oracle 客户端连接数据库 为了简化Oracle在个人电脑的使用,避免占用不必要的资源,可以不安装Oracle客户端.方法是:使用Oracle I ...
- hibernate框架学习笔记12:查询优化
类级别查询优化: 创建一个实体类: package domain; import java.util.HashSet; import java.util.Set; //客户实体 public clas ...
- Maven+SSM框架搭建【spring+springmvc+mybatis】
本案例用到:ssm[spring+springmvc+mybatis]框架 数据库:mysql (推荐使用mysql 或者 sqlserver .oracle太大,一般大型项目才会用到) 开发工具: ...
- Alpha冲刺Day3
Alpha冲刺Day3 一:站立式会议 今日安排: 我们把项目大体分为四个模块:数据管理员.企业人员.第三方机构.政府人员.数据管理员这一模块,数据管理员又可细分为两个模块:基础数据管理和风险信息管理 ...
- router问题
var http = require("http"); var router = require("./router.js"); //创建服务器 var ser ...
- 同一个页面同时拥有collectionView和navigationBar和tabBar时可能遇到的问题
写一个页面的时候,遇到了页面加载时候collectionView的最下面少了49个像素的位置,切换去别的页面之后,再返回,又变回正常,多方求解无果后,发现原来是系统自带的适应功能导致的,加入以下代码即 ...
- 使用SecureCRTP 连接生产环境的web服务器和数据库服务器
一.使用SecureCRTP 连接生产环境的web服务器 首先,需要知道以下参数信息: 1.web服务器的ip地址 2.服务器的端口号 3.会话连接的用户名和密码 4.服务器的用户名 ...
- Scala 操作符与提取器
实际上Scala没有操作符, 只是以操作符的格式使用方法. 操作符的优先级取决于第一个字符(除了赋值操作符), 而结合性取决于最后一个字符 Scala的操作符命名更加灵活:) 操作符 中置操作符(In ...
- ctf变量覆盖漏洞:
1.变量覆盖: ①:针对extract函数的变量覆盖漏洞: <?php @error_reporting(E_ALL^E_NOTICE); require('config.php'); if($ ...