React受控组件和非受控组件
受控组件和非受控组件主要是用来解决表单组件状态谁来控制的问题。因为用户的输入会反应在界面上,相当于视图的状态发生了变化,而react是通过虚拟DOM比对修改视图的,这里就要决定谁来控制表单组件的状态。由用户直接控制的称为非受控组件,而由react的控制的,称为受控组件。
1. 非受控组件
没有设置value/checked的表单组件,表单数据有DOM元素本身处理
组件自己控制组件的状态,一般父组件会给它一个初始值(通过defaultValue属性)
defaultValue/defaultChecked设置默认值,首次生效,重新渲染后则不生效,有value时也不生效
input元素本身也有defaultValue属性,可以设置或返回其默认值
defaultValue需要在constructor或者componentWillMount设置设置state
其他周期中设置的在render后无法看到默认值
形如:
<input type="text" />
非受控组件与普通input一致,用户的输入正常显示,由用户来控制组件的状态。
非受控组件通常和ref结合在一起,通过node.value方式来获取dom节点的值,这种方式适合不需要知道实时状态,只需要提交的表单组件。
import React, { Component } from 'react';
class UnControlled extends Component {
handleSubmit = (e) => {
console.log(e);
e.preventDefault();
console.log(this.name.value);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="text" ref={i => this.name = i} defaultValue="BeiJing" />
<button type="submit">Submit</button>
</form>
);
}
}
export default UnControlled;
非受控组件的父子组件形式:
//父组件
class Parent extends Component {
render() {
return
<NumberInput defaultValue=20 />;
}
} //子组件NumberInput
class NumberInput extends Component {
render() {
return
<input type="text" className="NumberInput"
defaultValue={this.props.defaultValue} /> }
}
2. 受控组件
设置了value/checked的表单组件,其vaule/checked必须是react组件的state,并且有onChange事件来修改state
组件自己不更新值,而是把值传递给父组件,让父组件决定是否更改。
形如:
<input value="this.state.name" onChange="fHandleChange" />
受控组件通常如下:
<input
type="text"
value={this.state.value}
onChange={(e) => {
this.setState({
value: e.target.value.toUpperCase(),
});
}}
/>
1. 可以通过初始state中设置表单的默认值;
2. 每当表单的值发生变化时,调用onChange事件处理器;
3. 事件处理器通过合成事件对象e拿到改变后的状态,并更新应用的state.
4. setState触发视图的重新渲染,完成表单组件值得更新
受控组件不同表单组件的处理形式:

受控组件的说明:
1. 受控组件会频繁触发change事件,会带来一定的性能损耗,但是影响不大,为了状态的统一,值得一做
2. 受控组件要value和onChange事件配合使用,写起来麻烦,有一些简化手段:
1. 封装一个InputItem组件,将value和change作为参数
2. 使用一个onChange方法处理多个Input,内部使用switch来分别处理不同组件的状态
受控组件的父子组件形式:
//父组件
class Parent extends Component {
constructor(props) {
super(props);
this.state = {value: 1};
this.onChangeHandle = this.onChange.bind(this);
}
onChange(event) {
//处理值
if (改) {
this.setState({value: event.target.value});
}
}
render() {
return
<NumberInput value={this.state.value} onChange={this.onChangeHandle} />
;
}
}
//子组件NumberInput
class NumberInput extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
}; this.onChangeHandle = this.onChange.bind(this);
}
//接收到新的属性时更新state
componentWillReceiveProps(nextProps) {
this.setState({
value: nextProps.value
});
}
onChange(event) {
//通知父组件值更新了
this.props.onChange(event);
}
render() {
return
<input type="text" className="NumberInput"
value={this.state.value}
onChange={this.onChangeHandle} />
}
}
3. 混合组件(既支持受控组件也支持非受控组件的组件)
//父组件
//把子组件当受控组件(传递value和onChange):
render() {
return <NumberInput value={this.state.value} onChange={this.onChangeHandle} />
}
//把子组件当非受控组件(传递defalutValue):
render() {
return <NumberInput defaultValue={this.state.value} />
} //子组件NumberInput
class NumberInput extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
};
this.onChangeHandle = this.onChange.bind(this);
}
//接收到新的属性时更新state
componentWillReceiveProps(nextProps) {
this.setState({
value: nextProps.value
});
}
onChange(event) {
//通知父组件值更新了
this.props.onChange(event);
}
render() {
let val = {};
//判断组件的props属性是否有value属性,有的话,是受控组件,没有的话是非受控组件
this.props['value'] === undefined ?
(val = {'defaultValue': this.props.defaultValue}) :
(val = {'value': this.state.value});
//使用对象和分解运算符来完成不同属性的切换
return <input type="text" className="NumberInput"
{...val}
onChange={this.onChangeHandle} />;
}
}
混合组件的基本原则:
1. props.value总是有比内部state.value跟高的优先级
2. 组件中所有的变化都应该同步到内部的state.value,并通过执行props.onChange来触发更新
3. 当组件接受新的props的时候,将props.value反映给state.value
4. 在优先值发生变化后更新组件
有了以上原则,就可以实现一个装饰器,hybridCtrl,来将一个普通组件转换为一个混合组件
@hybridCtrl
class App extends React.Component {
static propTypes = {
value: React.PropTypes.any,
} state = {
_value: '',
} mapPropToState(controlledValue) {
// your can do some transformations from `props.value` to `state._value`
} handleChange(newVal) {
// it's your duty to handle change events and dispatch `props.onChange`
}
}
结论:
1、为什么我们需要混合组件?
我们应该创建同时受控和非受控的组件,就像原生的元素那样。
2、混合组件主要思想是?
同时维护props.value和state.value的值。props.value在展示上拥有更高的优先级,state.value代表着组件真正的值。
混合组件的一个例子(作者是一村又一庄):
1、支持传入默认值;
2、可控:组件外部修改props可改变input组件的真实值及显示值;
3、非可控:输入框中输入值,可同时改变input组件的真实值及显示值。
示例代码地址:https://github.com/abell123456/hybrid-component
4. 受控组件和不受控组件的使用区别

5. 表单组件的几个重要属性
1.状态属性
React的form组件提供了几个重要的属性,用来显示组件的状态
value: 类型为text的input组件,textarea组件以及select组件都借助value prop来展示应用的状态
checked: 类型为radio或checkbox的组件借助值为boolean类型的selected prop来展示应用的状态
selected: 该属性可作用于select组件下面的option上,React并不建议这种方式表示状态.而推荐在select组件上使用value的方式
2.事件属性
当状态属性改变时会触发onChange事件属性.受控组件中的change事件与HTML DOM中提供的input事件更为类似
参考:https://segmentfault.com/a/1190000012404114
https://blog.csdn.net/jianruoche/article/details/79238831
https://blog.csdn.net/fendouzhe123/article/details/52121704
https://www.cnblogs.com/aichenxy/p/6758004.html
React受控组件和非受控组件的更多相关文章
- React:受控组件与非受控组件混用实战 - 译文
原文链接:React: hybrid controlled components in action 受控组件 非受控组件 混用受控组件和非受控组件 原则一 原则二 原则三 原则四 实施方案 总结 F ...
- 浅谈react受控组件与非受控组件
引言 最近在使用蚂蚁金服出品的一条基于react的ant-design UI组件时遇到一个问题,编辑页面时input输入框会展示保存前的数据,但是是用defaultValue就是不起作用,输入框始终为 ...
- react 表单(受控组件和非受控组件)
我们知道表单元素与其他的普通DOM元素来说是不一样的,它们保存了自己的一些状态. 我们主要说的就是表单元素中的受控组件和非受控组件. 受控组件就是这个组件的状态是我们(react)控制的,这个组件的行 ...
- react中 受控组件和 非受控组件 浅析
一 受控组件 顾名思义,受控 也就是能够被控制,简而言之也就是 该组件ui的显示或者内部state逻辑的变化依赖外部的 props的传入. 二 非受控组件 顾名思义,非受控,也就是内部的视图变化,st ...
- react第十一单元(受控组件和非受控组件-实现类似于vue双向绑定的功能)
第十一单元(受控组件和非受控组件-实现类似于vue双向绑定的功能) #课程目标 理解因为react的单向数据流 理解表单组件会因为react数据流变的不好维护 理解受控组件与非受控组件的实质区别 理解 ...
- Vue父子组件及非父子组件如何通信
1.父组件传递数据给子组件 父组件数据如何传递给子组件呢?可以通过props属性来实现 父组件: 子组件通过props来接收数据: 方式1: 方式2 : 方式3: 这样呢,就实现了父组件向子组件传递数 ...
- 学习React系列(四)——受控组件与非受控组件
受控组件:通过组件的状态与属性的改变来控制组件 不可控组件:直接通过底层的dom来控制组件(具体来说就是通过绑定再底层dom上的方法来实现的,比如说ref,onChange) 受控组件 functio ...
- React 受控组件和非受控组件
需求用户名自动获取 onChange用户状态发生改变 就获取值 就是时时获取值 使用onChange 点击按钮 获取密码 只要绑定了点击事件 就可以获取值 通过 let usercont=event. ...
- React组件之间通过Props传值的技巧(小案例,帮助体会理解props、state、受控组件和非受控组件等)
本文重要是根据react小书上的一个很简单的例子改编的,加上自己的学习理解,希望可以通过实际案例让大家对概念有更清晰的理解,当然也希望能一块学习. import React,{Component} f ...
随机推荐
- 「国庆训练&知识学习」图的最大独立集与拓展(Land of Farms,HDU-5556)
题意 一个\(N*M\)的矩阵,其中"."代表空地,"0-9"代表古代建筑,我们如果选择了一个编号的古代建筑想要建立,那么对应就要将全部该编号的建筑建立起来,如 ...
- html div内第二行文字显示不下的时候才用省略号代替 css实现
有时候文字太多,但为了美观想要在第二行的时候才显示省略号,而不是第一行超出马上就出现省略号 下面是css代码: overflow:hidden;text-overflow: ellipsis;//显示 ...
- Git一分钟系列--快速安装git客户端
在项目开发过程中,几乎所有公司都会用到版本控制工具来管理自己的项目资源文件,比如Git,SVN. 什么是svn? 版本控制软件,通过svn来实现版本控制首先需要搭建一个服务器,在服务器上创建仓库保存项 ...
- Java开发工程师(Web方向) - 02.Servlet技术 - 第1章.Servlet
第1章--Servlet Servlet简介 Servlet应用于? 浏览器发出HTTP请求,服务器接收请求后返回响应给浏览器. 接收请求后到返回响应之间: 服务器将请求对象转交给Servlet容器 ...
- laravel 的DB::raw() 语法使用
z之前在项目中遇到一个问题,复杂的sql查询,用laravel的查询构造器,非常的不方便,各种查询条件拼接一长串拼得脑瓜疼:然后想使用原生的sql语句来查询,然后又使用不了laravel的pagina ...
- docker学习2
今天继续学习docker! 搜索镜像 docker search centos 下载镜像 docker pull name(镜像名字) 查看镜像docker images 字段含义分析: TAG:仓库 ...
- 一个五位数ABCDE乘以9,得到EDCBA,求此五位数
此题是面试时某面试官突然抛出的,要求逻辑分析推导,不许编码,5分钟时间算出来最终结果,当然,最终没有完全推算出来 下面是编码实现 #一个五位数ABCDE*9=EDCBA,求此数 for a in ra ...
- 十面阿里,七面头条,六个Offer,春招结束
作者:jkgeekjack链接:https://www.nowcoder.com/discuss/80156?type=0&order=0&pos=13&page=2来源:牛客 ...
- HDU 4617 Weapon(三维几何)
Problem Description Doctor D. are researching for a horrific weapon. The muzzle of the weapon is a c ...
- css贝塞尔曲线模仿饿了么购物车小球动画
在线观看贝塞尔曲线值:传送门 在线观看动画效果:传送门 代码: <!DOCTYPE html> <html> <head> <meta charset=&qu ...