浅谈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 相关文章推荐
javascript内存管理详细解析
Nov 11 Javascript
js中的json对象详细介绍
Oct 29 Javascript
Node.js异步I/O学习笔记
Nov 04 Javascript
jQuery实现的图文高亮滚动切换特效实例
Aug 10 Javascript
原生js实现弹出层登录拖拽功能
Dec 05 Javascript
JavaScript调试的多个必备小Tips
Jan 15 Javascript
jQuery插件FusionCharts绘制2D环饼图效果示例【附demo源码】
Apr 10 jQuery
vue axios用法教程详解
Jul 23 Javascript
利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解
Nov 20 Javascript
详解在vue-cli中使用graphql即vue-apollo的用法
Sep 08 Javascript
ES7之Async/await的使用详解
Mar 28 Javascript
详解JavaScript中的this指向问题
Feb 05 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
新手学习PHP的一些基础知识分享
2011/07/27 PHP
PHP持久连接mysql_pconnect()函数使用介绍
2012/02/05 PHP
Yii2 rbac权限控制之rule教程详解
2016/06/23 PHP
PHP 布尔值的自增与自减的实现方法
2018/05/03 PHP
php实现简单四则运算器
2020/11/29 PHP
PHP的重载使用魔术方法代码实例详解
2021/02/26 PHP
javascript字典探测用户名工具
2006/10/05 Javascript
js用拖动滑块来控制图片大小的方法
2015/02/27 Javascript
node.js抓取并分析网页内容有无特殊内容的js文件
2015/11/17 Javascript
简要了解jQuery移动web开发的响应式布局设计
2015/12/04 Javascript
JS实现图片上传预览功能
2016/11/21 Javascript
JS实现图片预加载之无序预加载功能代码
2017/05/12 Javascript
简单快速的实现js计算器功能
2017/08/17 Javascript
vuex实现登录状态的存储,未登录状态不允许浏览的方法
2018/03/09 Javascript
vue-resource请求实现http登录拦截或者路由拦截的方法
2018/07/11 Javascript
JavaScript模板引擎实现原理实例详解
2018/12/14 Javascript
vuex页面刷新后数据丢失的方法
2019/01/17 Javascript
Vue使用自定义指令实现拖拽行为实例分析
2020/06/06 Javascript
python中使用sys模板和logging模块获取行号和函数名的方法
2014/04/15 Python
Python 安装setuptools和pip工具操作方法(必看)
2017/05/22 Python
python jieba分词并统计词频后输出结果到Excel和txt文档方法
2018/02/11 Python
Python 十六进制整数与ASCii编码字符串相互转换方法
2018/07/09 Python
tensorflow: variable的值与variable.read_value()的值区别详解
2018/07/30 Python
使用python判断jpeg图片的完整性实例
2019/06/10 Python
Django中reverse反转并且传递参数的方法
2019/08/06 Python
python2和python3应该学哪个(python3.6与python3.7的选择)
2019/10/01 Python
python文件处理fileinput使用方法详解
2020/01/02 Python
使用HTML5 Canvas API绘制弧线的教程
2016/03/22 HTML / CSS
施华洛世奇澳大利亚官网:SWAROVSKI澳大利亚
2017/01/06 全球购物
英国婴儿和儿童服装网站:Vertbaudet
2018/04/02 全球购物
西班牙自行车和跑步商店:Alltricks
2018/07/07 全球购物
英国No.1体育用品零售商:SportsDirect.com
2019/10/16 全球购物
八年级英语教学反思
2014/01/09 职场文书
军训自我鉴定范文
2014/02/13 职场文书
某某幼儿园的教育教学管理调研分析报告
2019/11/29 职场文书
ant design vue的form表单取值方法
2022/06/01 Vue.js