受控组件和非受控组件主要是用来解决表单组件状态谁来控制的问题。因为用户的输入会反应在界面上,相当于视图的状态发生了变化,而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. 「日常训练」School Marks(Codeforces Round 301 Div.2 B)

    题意与分析(CodeForces 540B) 题意大概是这样的,有一个考试鬼才能够随心所欲的控制自己的考试分数,但是有两个限制,第一总分不能超过一个数,不然就会被班里学生群嘲:第二分数的中位数(科目数 ...

  2. Java开发工程师(Web方向) - 04.Spring框架 - 第2章.IoC容器

    第2章.IoC容器 IoC容器概述 abstract: 介绍IoC和bean的用处和使用 IoC容器处于整个Spring框架中比较核心的位置:Core Container: Beans, Core, ...

  3. 博客更换至 www.zhaoch.top

    博客更换至 www.zhaoch.top 随手拷了一些链接 http://www.zhaoch.top/操作系统/linux/常用命令备忘.html http://www.zhaoch.top/操作系 ...

  4. python爬虫基础之一(爬淘宝)

    没想到python如此强大, 今天看一会视频学会了一段python爬虫 这就是我今天学到的内容爬去淘宝网关于书包的一些信息,包括价格, #coding=utf-8 import requests#导入 ...

  5. java实现遍历一个字符串的每一个字母(总结)

    基础:牢记字符串操作的各种方法: ​​​ ​ String s = "aaaljlfeakdsflkjsadjaefdsafhaasdasd"; // 出现次数 int num = ...

  6. String和StringBuffer以及StringBuilder的区别

    今天在读<java编程思想>的时间,在看到String和StringBuffer以及StringBuffer这三个类的时间,做一个随笔小结,为自己的面试做好准备! 一:String,Str ...

  7. Cassandra 类型转换限制

    原文地址:http://stackoverflow.com/questions/31880381/cassandra-alter-column-type-which-types-are-compati ...

  8. Struts2中Action各种转发类型

    Struts2:Action中result的各种转发类型: 内部请求转发dispatcher(默认值) redirect.redirectAction.plainText1.redirect是重定向到 ...

  9. "Hello world!"团队第一次会议

    今天是我们"Hello world!"团队第一次召开会议,今天的会议可能没有那么正式,但是我们一起确立了选题——基于WEB的售票系统.博客内容是: 1.会议时间 2.会议成员 3. ...

  10. 3dContactPointAnnotationTool开发日志(二二)

      昨天是实现了显示GameObject子GameObject的选项卡功能,今天就是要让statusPanel可以控制它们的位置.旋转和缩放了.   没什么难的,对应选项卡绑定上对应的物体或子物体即可 ...