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

    对象属性与继承关系: 对象属性 1. 显示属性 - 开发者手动定义的,直接看的到的 2. 隐式属性 - 系统根据需求,自动创建的对象 - objects 它是model.Manager对象 - 当我们 ...

  2. 换抵挡装置 (Kickdown,ACM/ICPC NEERC 2006,UVa1588

    题目描述:算法竞赛入门经典习题3-11 题目思路:1.两长条移动匹配 2.上下调换,取小者 #include <stdio.h> #include <string.h> int ...

  3. CSP201703-1:分蛋糕

    引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...

  4. OpenMPI源码剖析2:ompi_mpi_errors_are_fatal_comm_handler函数

    上一篇文章说道,初始化失败会有一个函数调用: ompi_mpi_errors_are_fatal_comm_handler(NULL, NULL, message); 所以这里简单地进入了 ompi_ ...

  5. 【Linux】Face Recognition的封装

    使用虹软的人脸识别 写了一个linux下的Face Recognition的封装,当作是练习. C++的封装,结合opencv,使用方便.https://github.com/zacario-li/F ...

  6. [ Continuously Update ] The Paper List of Image / Video Captioning

    Papers Published in 2018 Convolutional Image Captioning - Jyoti Aneja et al., CVPR 2018 - [ Paper Re ...

  7. [C++] Class (part 1)

    The fundamental ideas behind classes are data abstraction and encapsulation. Data abstraction is a p ...

  8. 基于NABCD评论“欢迎来怼”团队Alpha版作品

    NABCD分析 N(需求) 随着博客园网页版的出现,大家希望能够随时看自己博客,查看别人的博客,以及写博客,评论博客等功能.对于学生的我们,及时了解作业的动态很重要,电脑不能随时携带,但手机随身携带, ...

  9. P4编程环境搭建遇到的问题与解决方法

    在经历了无数的折腾之后,算是折腾,最后采用的是陈翔学长的脚本加上可爱的shell调整装好的. 链接:p4Install 也许是ubuntu18.04的问题,也有可能是我自己把这个系统折腾的有点杂乱的原 ...

  10. 转 高性能IO模型浅析

    高性能IO模型浅析 转自:http://www.cnblogs.com/fanzhidongyzby/p/4098546.html 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: ( ...