受控组件和非受控组件主要是用来解决表单组件状态谁来控制的问题。因为用户的输入会反应在界面上,相当于视图的状态发生了变化,而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受控组件和非受控组件的更多相关文章

  1. React:受控组件与非受控组件混用实战 - 译文

    原文链接:React: hybrid controlled components in action 受控组件 非受控组件 混用受控组件和非受控组件 原则一 原则二 原则三 原则四 实施方案 总结 F ...

  2. 浅谈react受控组件与非受控组件

    引言 最近在使用蚂蚁金服出品的一条基于react的ant-design UI组件时遇到一个问题,编辑页面时input输入框会展示保存前的数据,但是是用defaultValue就是不起作用,输入框始终为 ...

  3. react 表单(受控组件和非受控组件)

    我们知道表单元素与其他的普通DOM元素来说是不一样的,它们保存了自己的一些状态. 我们主要说的就是表单元素中的受控组件和非受控组件. 受控组件就是这个组件的状态是我们(react)控制的,这个组件的行 ...

  4. react中 受控组件和 非受控组件 浅析

    一 受控组件 顾名思义,受控 也就是能够被控制,简而言之也就是 该组件ui的显示或者内部state逻辑的变化依赖外部的 props的传入. 二 非受控组件 顾名思义,非受控,也就是内部的视图变化,st ...

  5. react第十一单元(受控组件和非受控组件-实现类似于vue双向绑定的功能)

    第十一单元(受控组件和非受控组件-实现类似于vue双向绑定的功能) #课程目标 理解因为react的单向数据流 理解表单组件会因为react数据流变的不好维护 理解受控组件与非受控组件的实质区别 理解 ...

  6. Vue父子组件及非父子组件如何通信

    1.父组件传递数据给子组件 父组件数据如何传递给子组件呢?可以通过props属性来实现 父组件: 子组件通过props来接收数据: 方式1: 方式2 : 方式3: 这样呢,就实现了父组件向子组件传递数 ...

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

    受控组件:通过组件的状态与属性的改变来控制组件 不可控组件:直接通过底层的dom来控制组件(具体来说就是通过绑定再底层dom上的方法来实现的,比如说ref,onChange) 受控组件 functio ...

  8. React 受控组件和非受控组件

    需求用户名自动获取 onChange用户状态发生改变 就获取值 就是时时获取值 使用onChange 点击按钮 获取密码 只要绑定了点击事件 就可以获取值 通过 let usercont=event. ...

  9. React组件之间通过Props传值的技巧(小案例,帮助体会理解props、state、受控组件和非受控组件等)

    本文重要是根据react小书上的一个很简单的例子改编的,加上自己的学习理解,希望可以通过实际案例让大家对概念有更清晰的理解,当然也希望能一块学习. import React,{Component} f ...

随机推荐

  1. php常用几个数组的区别

    本文主要介绍的php数组函数主要有:sort.rsort.asort.arsort.ksort.krsort 测试数据定义一个关联数组如下: $data=[ 'f'=>123, 'b'=> ...

  2. wordlist 4

    wordlist 4 desolate 啥啥啥lete adj. 荒凉的:无人烟的 repression depression n. 抑制,[心理] 压抑:镇压 / n. 沮丧:忧愁:抑郁症: spe ...

  3. [USACO09Open] Tower of Hay 干草塔

    为了调整电灯亮度,贝西要用干草包堆出一座塔,然后爬到牛棚顶去把灯泡换掉.干草包会从传送带上运来,共会出现N包干草,第i包干草的宽度是W i ,高度和长度统一为1.干草塔要从底层开始铺建.贝西会选择最先 ...

  4. Bootstrap框架(图标)

    Glyphicons 字体图标 所有可用的图标 包括250多个来自 Glyphicon Halflings 的字体图标.Glyphicons Halflings 一般是收费的,但是他们的作者允许 Bo ...

  5. Jedis 与 MySQL的连接线程安全问题

    Jedis的连接是非线程安全的 下面是set命令的执行过程,简单分为两个过程,客户端向服务端发送数据,服务端向客户端返回数据,从下面的代码来看:从建立连接到执行命令是没有进行任何并发同步的控制 pub ...

  6. Learning Spatial-Temporal Regularized Correlation Filters for Visual Tracking---随笔

    Learning Spatial-Temporal Regularized Correlation Filters for Visual Tracking DCF跟踪算法因边界效应,鲁棒性较差.SRD ...

  7. 手动在Windows上创建kafka环境

    一 主要内容请移步 参考文章 二 一点小问题 安装上面的参考文章完成配置,并且尝试传输消息后,我尝试去查看kafka的消息数据,目录是{logdir}/test-0/00000000000000.lo ...

  8. 关于localStorage的实际应用

    在客户端存储数据 HTML5 提供了两种在客户端存储数据的新方法: localStorage - 没有时间限制的数据存储 sessionStorage - 针对一个 session 的数据存储 之前, ...

  9. Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件

    作者 : 万境绝尘 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365 示例代码下载 : -- CSDN : htt ...

  10. 由作业题引发对C++引用的一些思考

    首先分析一段代码: #include <bits/c++config.h> #include <ostream> #include <iostream> #incl ...