React组件refs的使用详解


Posted in Javascript onFebruary 09, 2018

ref顾名思义我们知道,其实它就可以被看座是一个组件的参考,也可以说是一个标识。作为组件的属性,其属性值可以是一个字符串也可以是一个函数。

其实,ref的使用不是必须的。即使是在其适用的场景中也不是非用不可的,因为使用ref实现的功能同样可以转化成其他的方法来实现。但是,既然ref有其适用的场景,那也就是说ref自有其优势。关于这一点和ref的适用场景,官方文档中是这样说的:

在从 render 方法中返回 UI 结构之后,你可能想冲出 React 虚拟 DOM 的限制,在 render 返回的组件实例上调用某些方法。通常来说,这样做对于应用中的数据流动是不必要的,因为活跃的数据( Reactive data )流总是确保最新的 props 被传递到每一个从 render() 输出的子级中去。然而,仍然有几个场景使用这种方式是必须的,或者说是有益的:查找渲染出的组件的DOM标记(可以认为是DOM的标识ID),在一个大型的非React应用中使用React组件或者是将你现有的代码转化成React。

下面我们来看这样的一个场景(下面的例子经常被用于ref的讲解,可见下面描述的场景应该是比较经典的):通过某个事件使<input />元素的值被设为空字符串,然后使该<input />元素获得焦点。

var App = React.createClass({
  getInitialState: function() {
   return {userInput: ''};
  },
  handleChange: function(e) {
   this.setState({userInput: e.target.value});
  },
  clearAndFocusInput: function() {
   this.setState({userInput: ''}); // 设置值为空字符串
        //这里想要实现获得焦点   
  },
  render: function() {
   return (
    <div>
     <input
      value={this.state.userInput}
      onChange={this.handleChange}
     />
          <input type="button"
           value="Reset And Focus"
           onClick={this.clearAndFocusInput}
        />
    </div>
   );
  }
 });

在上面例子中,我们已经实现了点击按钮通知input元素将值设为空字符串,但是还没有实现使input元素获得焦点。这实现起来有些困难,因为在render()中返回的并不是实际的子组件的组合,仅仅是一个特定时间特定实例的描述。这句话感觉挺绕的,其实render返回的是虚拟的DOM,并不是真实的DOM。因此我们不需要仅仅着眼于那些从render()中返回的那些组件。

那说到这,对于我们如何实现获得焦点并没有太大的帮助。要想实现获得焦点这个功能我们需要借助ref来实现。上面我们提到过ref的值有两种类型,一种是字符串、一种是回调函数。

ref字符串上属性

React支持一个特殊的属性,你可以将这个属性加在任何通过render()返回的组件中。这也就是说对render()返回的组件进行一个标记,可以方便的定位的这个组件实例。这就是ref的作用。

ref的形式如下

<input ref="myInput" />

要想访问这个实例,可以通过this.refs来访问:

this.refs.myInput

先前版本中,我们可以通过React.findDOMNode(this.refs.myInput)来访问组件的DOM。但是现在,已经放弃了findDOMNode函数了,可以直接使用this.refs.myInput来进行访问。

ref回调函数

ref属性也可以是一个回调函数而不是一个名字。   这个函数将要在组件被挂载之后立即执行。这个参照的组件将会作为该函数的参数,这个函数可以立即使用这个组件参数,当然也可以将其保存供以后使用。

其形式也比较简单:

render: function() {
  return <TextInput ref={(c) => this._input = c} } />;
},
componentDidMount: function() {
  this._input.focus();
},

或者是

render: function() {
  return (
   <TextInput
    ref={function(input) {
     if (input != null) {
      input.focus();
     }
    }} />
  );
},

这里需要注意,当这个参照组件被卸载并且这个ref改变的时候,先前的ref的参数值将为null。这将有效的防止了内存的泄露。所以在上面代码中会有if判断:

if(input != null){
     input.focus();
}

上面介绍了ref的使用场景和方法,下面我们就将上面的例子来补充完整,从而实现获得焦点的功能

var App = React.createClass({
  getInitialState: function() {
    return {userInput: ''};
  },
  handleChange: function(e) {
    this.setState({userInput: e.target.value});
  },
  clearAndFocusInput: function() {
    this.setState({userInput: ''}); // Clear the input
    // We wish to focus the <input /> now!
    if (this.refs.myTextInput !== null) {
      this.refs.myTextInput.focus();
    }
  },
  render: function() {
    return (
      <div>
        <input
          value={this.state.userInput}
          onChange={this.handleChange}
          ref=”myTextInput”   
                     />
        <input
          type="button"
          value="Reset And Focus"
          onClick={this.clearAndFocusInput}
          />
      </div>
    );
  }
});
ReactDOM.render(
  <App />,
  document.getElementById('content')
);

在这个例子中, render 函数返回一个 <input /> 实例的描述。但是真正的实例通过 this.refs. myTextInput获取。只要 render 返回的某个子组件带有 ref="myTextInput" ,this.refs. myTextInput就会获取到正确的实例。

上面就是ref的所有内容,更多关于ref的介绍可以参考Ref to Components。

对于ref我们就介绍到这,希望本文对大家有所帮助。也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js每次Title显示不同的名言
Sep 25 Javascript
js弹出层之1:JQuery.Boxy (二)
Oct 06 Javascript
jquery图片切换插件
Mar 16 Javascript
Vue.js 2.0中select级联下拉框实例
Mar 06 Javascript
js实现拖拽上传图片功能
Aug 01 Javascript
使用vue-resource进行数据交互的实例
Sep 02 Javascript
mpvue中配置vuex并持久化到本地Storage图文教程解析
Mar 15 Javascript
JavaScript设计模式之职责链模式应用示例
Aug 07 Javascript
js中的reduce()函数讲解
Jan 18 Javascript
一些你可能不熟悉的JS知识点总结
Mar 15 Javascript
vue+swiper实现左右滑动的测试题功能
Oct 30 Javascript
vue图片裁剪插件vue-cropper使用方法详解
Dec 16 Vue.js
详解vue-cli项目中的proxyTable跨域问题小结
Feb 09 #Javascript
使用express搭建一个简单的查询服务器的方法
Feb 09 #Javascript
js自定义trim函数实现删除两端空格功能
Feb 09 #Javascript
JavaScript运行原理分析
Feb 09 #Javascript
vue 全选与反选的实现方法(无Bug 新手看过来)
Feb 09 #Javascript
详解如何在项目中使用jest测试react native组件
Feb 09 #Javascript
vue checkbox 全选 数据的绑定及获取和计算方法
Feb 09 #Javascript
You might like
php radio 单选框获取与保持值的实现代码
2010/05/15 PHP
php实现的短网址算法分享
2014/06/20 PHP
php利用cookies实现购物车的方法
2014/12/10 PHP
php获取本周开始日期和结束日期的方法
2015/03/09 PHP
php文件扩展名判断及获取文件扩展名的N种方法
2015/09/12 PHP
php简单实现文件或图片强制下载的方法
2016/12/06 PHP
PHP面向对象之事务脚本模式(详解)
2017/06/07 PHP
Laravel框架实现redis集群的方法分析
2017/09/14 PHP
thinkphp5 加载静态资源路径与常量的方法
2017/12/24 PHP
YII2框架中日志的配置与使用方法实例分析
2020/03/18 PHP
THINKPHP5分页数据对象处理过程解析
2020/10/28 PHP
破除一些网站复制、右键限制
2006/11/04 Javascript
javascript通过navigator.userAgent识别各种浏览器
2013/10/25 Javascript
eclipse导入jquery包后报错的解决方法
2014/02/17 Javascript
JavaScript运行机制之事件循环(Event Loop)详解
2014/10/10 Javascript
倾力总结40条常见的移动端Web页面问题解决方案
2016/05/24 Javascript
JS实现页面中所有img对象添加onclick事件及新窗口查看图片的方法
2016/12/27 Javascript
vue2.x 父组件监听子组件事件并传回信息的方法
2017/07/17 Javascript
解决Angular2 router.navigate刷新页面的问题
2018/08/31 Javascript
layui多图上传实现删除功能的例子
2019/09/23 Javascript
[45:46]2014 DOTA2国际邀请赛中国区预选赛5.21 HGT VS DT
2014/05/23 DOTA
Windows下用py2exe将Python程序打包成exe程序的教程
2015/04/08 Python
python检查字符串是否是正确ISBN的方法
2015/07/11 Python
Python替换月份为英文缩写的实现方法
2019/07/15 Python
在Tensorflow中实现梯度下降法更新参数值
2020/01/23 Python
基于Python实现下载网易音乐代码实例
2020/08/10 Python
使用Python画了一棵圣诞树的实例代码
2020/11/27 Python
HTML5中div、article、section的区别及使用介绍
2013/08/14 HTML / CSS
Space NK英国站:英国热门美妆网站
2017/12/11 全球购物
母亲80寿诞答谢词
2014/01/16 职场文书
品质标语大全
2014/06/21 职场文书
工地例会施工汇报材料
2014/08/22 职场文书
大学学生个人总结
2015/02/15 职场文书
专项资金申请报告
2015/05/15 职场文书
导游词之麻姑仙境
2019/11/18 职场文书
go goroutine 怎样进行错误处理
2021/07/16 Golang