浅谈react受控组件与非受控组件(小结)


Posted in Javascript onFebruary 09, 2018

我们都知道,有许多的web组件可以被用户的交互发生改变,比如:<input>,<select>,或者是我现在正在使用的富文本编辑器。这些组件在日常的开发中很不显眼,我们可以很轻易的通过输入一些内容或者设置元素的value属性来改变组件的值。但是,因为React是单向数据流绑定的,这些组件可能会变得失控:

1.一个维护它自己state里的value值的<Input>组件无法从外部被修改;

2.一个通过props来设置value值的<Input>组件只能通过外部控制来更新。

最近在使用蚂蚁金服出品的一条基于react的ant-design UI组件时遇到一个问题,编辑页面时input输入框会展示保存前的数据,但是是用defaultValue就是不起作用,输入框始终为空值而不是具体的传入的值。具体编辑页面中文本框相关的代码如下:

... //render方法上面的内容省略
 <FormItem
   label="问题描述:"
   hasFeedback
   {...props.formItemLayout}
 >
  <Input type="textarea" defaultValue={props.value}/>
</FormItem>
      //render下面的内容省略
      ...

在给代码段所属的组件传递value props后,文本框中的默认值一直为空,因为该页面所在的状态state中,value所对应的状态初始值为空,导致后续异步请求成功后改变value对应的状态中的值,仍然显示为空。

google一下具体原因,原来React的form表单组件中的defaultValue一经传递值后,后续改变defaultValue都将不起作用,被忽略了。

具体来说这是一种react非受控组件,其状态是在input的react内部控制,不受调用者控制。可以使用受控组件来实现。

下面就说说这个受控组件与非受控组件,它们都是基于react的form表单组件元素的,具体也可参考react官网这方面介绍

受控组件

就形式上来说,受控组件就是为某个form表单组件添加value属性;非受控组件就是没有添加value属性的组件;,受控组件的形式如下形式:

render: function() {
  return <input type="text" value="Hello!" />;
 }

添加了value 属性的表单组件元素其内部是不会维护自己状态state,组件的value值一旦设置某个具体值就始终是这个值,所以需要调用者来控制组件value的改变。

这种写法带来一个问题:渲染后的input组件的用户交互,用户输入的任何值将不起作用,input输入框中的值始终为Hello!。这与HTML中input表现不一致。

为此,为了控制该组件,就需要能能够控制input组件的值,需要借助其内部的状态state,即组件内部要维护一个状态state以便配合input组件的onChange和setState方法来完成对组件的控制;例如对上面形式可以进行封装一个inputItem组件,其内部维护一个state状态,具体代码如下:

export default class InputItem extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      value: ""
    }
  }

  componentWillReceiveProps(nextProps){
    this.setState({
      value: nextProps.value
    })
  }

  _onChange(evt){
    this.setState({
      value: evt.target.value
    })
  }

  render(){
    return (
      <input type="text" 
        value={this.state.value} 
        onChange={this._onChange.bind(this)}/>
    );
  }
}

这样就可以在外部像下面这样调用InputItem组件了:

<InputItem value={this.state.userName} />

这样就可以控制react的Input组件了,其实就是需要借助react的有状态component来完成,因为有状态component可以内部维护state。

非受控组件

表现形式上,react中没有添加value属性的表单组件元素就是非受控组件。表现形式如下:

<input type="text" />

非受控组件在底层实现时是在其内部维护了自己的状态state;这样表现出用户输入任何值都能反应到元素上。

总结

在使用react component时,都会遇到受控组件或者非受控组件;在目前,react组件推荐使用stateless component,但是使用该形式来实现react component时使用非受控组件到倒是没有什么大问题,若是需要控制受控元素就会有出现问题,表现在:

`受控组件`需要主动维护一个内部state状态的,而`stateless component`是无需维护组件的state状态的,二者有冲突。
所以,受控元素就不能使用stateless component来创建。

鉴于受控组件与非受控组件的特点,二者应用的地方也有所不同,主要表现在:

  1. 受控元素,一般用在需要动态设置其初始值的情况;例如某些form表单信息编辑时,input表单元素需要初始显示服务器返回的某个值然后进行编辑。
  2. 非受控元素, 一般用于无任何动态初始值信息的情况; 例如form表单创建信息时,input表单元素都没有初始值,需要用户输入的情况

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
(推荐一个超好的JS函数库)S.Sams Lifexperience ScriptClassLib
Apr 29 Javascript
各种常用浏览器getBoundingClientRect的解析
May 21 Javascript
Javascript学习笔记8 用JSON做原型
Jan 11 Javascript
Javascript 多浏览器兼容总结(实战经验)
Oct 30 Javascript
JavaScript更改字符串的大小写
May 07 Javascript
js实现微博发布小功能
Jan 12 Javascript
JavaScript实现的XML与JSON互转功能详解
Feb 16 Javascript
vue项目开发中setTimeout等定时器的管理问题
Sep 13 Javascript
详解Vue、element-ui、axios实现省市区三级联动
May 07 Javascript
vue实现动态按钮功能
May 13 Javascript
Node.js中文件系统fs模块的使用及常用接口
Mar 06 Javascript
js实现前端界面导航栏下拉列表
Aug 27 Javascript
基于Vue2.X的路由和钩子函数详解
Feb 09 #Javascript
Vuejs 单文件组件实例详解
Feb 09 #Javascript
vue-lazyload图片延迟加载插件的实例讲解
Feb 09 #Javascript
详解js正则表达式验证时间格式xxxx-xx-xx形式
Feb 09 #Javascript
在Vue中使用highCharts绘制3d饼图的方法
Feb 08 #Javascript
vue中使用ueditor富文本编辑器
Feb 08 #Javascript
React Native自定义控件底部抽屉菜单的示例
Feb 08 #Javascript
You might like
《魔兽世界》惊魂幻象将获得调整
2020/03/08 其他游戏
PHP实现HTML生成PDF文件的方法
2014/11/07 PHP
Yii2使用$this-&gt;context获取当前的Module、Controller(控制器)、Action等
2017/03/29 PHP
YII2框架中使用yii.js实现的post请求
2017/04/09 PHP
一些相见恨晚的 JavaScript 技巧
2010/04/25 Javascript
详解jQuery插件开发中的extend方法
2013/11/19 Javascript
在线所见即所得HTML编辑器的实现原理浅析
2015/04/25 Javascript
JS实现漂亮的窗口拖拽效果(可改变大小、最大化、最小化、关闭)
2015/10/10 Javascript
js轮盘抽奖实例分析
2020/04/17 Javascript
input框中的name和id的区别
2016/11/16 Javascript
Bootstrap modal使用及点击外部不消失的解决方法
2016/12/13 Javascript
jQuery代码实现实时获取时间
2017/01/29 Javascript
Vue实现自带的过滤器实例
2017/03/09 Javascript
从零开始学习Node.js系列教程六:EventEmitter发送和接收事件的方法示例
2017/04/13 Javascript
JS原生数据双向绑定实现代码
2017/08/14 Javascript
微信小程序项目实践之验证码倒计时功能
2018/07/18 Javascript
vue侧边栏动态生成下级菜单的方法
2018/09/07 Javascript
微信小程序 this.triggerEvent()的具体使用
2019/12/10 Javascript
JS中锚点链接点击平滑滚动并自由调整到顶部位置
2021/02/06 Javascript
[41:08]TNC vs VG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
python解决字典中的值是列表问题的方法
2013/03/04 Python
python 对类的成员函数开启线程的方法
2019/01/22 Python
PyTorch搭建多项式回归模型(三)
2019/05/22 Python
pymysql模块的操作实例
2019/12/17 Python
解决pycharm中导入自己写的.py函数出错问题
2020/02/12 Python
CSS3制作日历实现代码
2012/01/21 HTML / CSS
Blue Nile台湾:钻石珠宝商,订婚首饰、结婚戒指和精品首饰
2017/11/24 全球购物
Helly Hansen工作服美国官方网上商店:为最恶劣的环境
2019/09/04 全球购物
普通党员对照检查材料
2014/08/28 职场文书
党员“四风”问题批评与自我批评思想汇报
2014/10/06 职场文书
群众路线四风自我剖析材料
2014/10/08 职场文书
2014酒店客房部工作总结
2014/12/16 职场文书
冬季作息时间调整通知
2015/04/24 职场文书
2015年档案管理员工作总结
2015/05/13 职场文书
Java网络编程之UDP实现原理解析
2021/09/04 Java/Android
JavaScript流程控制(循环)
2021/12/06 Javascript