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 相关文章推荐
JavaScript 监听textarea中按键事件
Oct 08 Javascript
jQuery中的bind绑定事件与文本框改变事件的临时解决方法
Aug 13 Javascript
基于jQuery捕获超链接事件进行局部刷新代码
May 10 Javascript
利用CSS3在Angular中实现动画
Jan 15 Javascript
简单实现js倒计时功能
Feb 13 Javascript
Bootstrap3多级下拉菜单
Feb 24 Javascript
微信小程序定位当前城市的方法
Jul 19 Javascript
angular实现input输入监听的示例
Aug 31 Javascript
解决vue项目nginx部署到非根目录下刷新空白的问题
Sep 27 Javascript
微信小程序生成分享海报方法(附带二维码生成)
Mar 29 Javascript
微信内置浏览器图片查看器的代码实例
Oct 08 Javascript
vue组件中节流函数的失效的原因和解决方法
Dec 02 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
中国广播史趣谈 — 几个历史第一次
2021/03/01 无线电
PHP Memcached应用实现代码
2010/02/08 PHP
PHP similar_text 字符串的相似性比较函数
2010/05/26 PHP
php实现获取及设置用户访问页面语言类
2014/09/24 PHP
Smarty3配置及入门语法
2017/02/22 PHP
延时重复执行函数 lLoopRun.js
2007/05/08 Javascript
浅谈jQuery页面的滚动位置scrollTop、scrollLeft
2015/05/19 Javascript
WebGL利用FBO完成立方体贴图效果完整实例(附demo源码下载)
2016/01/26 Javascript
jQuery基于函数重载实现自定义Alert函数样式的方法
2016/07/27 Javascript
老生常谈jquery id选择器和class选择器的区别
2017/02/12 Javascript
react.js组件实现拖拽复制和可排序的示例代码
2018/08/20 Javascript
vue实现绑定事件的方法实例代码详解
2019/06/20 Javascript
速记Python布尔值
2017/11/09 Python
Python装饰器原理与用法分析
2018/04/30 Python
Python如何爬取微信公众号文章和评论(基于 Fiddler 抓包分析)
2019/06/28 Python
PYQT5开启多个线程和窗口,多线程与多窗口的交互实例
2019/12/13 Python
Python注释、分支结构、循环结构、伪“选择结构”用法实例分析
2020/01/09 Python
tensorflow 利用expand_dims和squeeze扩展和压缩tensor维度方式
2020/02/07 Python
Anaconda配置pytorch-gpu虚拟环境的图文教程
2020/04/16 Python
如何配置关联Python 解释器 Anaconda的教程(图解)
2020/04/30 Python
Keras中的多分类损失函数用法categorical_crossentropy
2020/06/11 Python
Keras在训练期间可视化训练误差和测试误差实例
2020/06/16 Python
Python如何操作docker redis过程解析
2020/08/10 Python
Python之京东商品秒杀的实现示例
2021/01/06 Python
adidas官方旗舰店:德国运动用品制造商
2017/11/25 全球购物
Unix如何添加新的用户
2014/08/20 面试题
Servlet面试题库
2015/07/18 面试题
竞聘演讲稿范文
2014/01/12 职场文书
青春无悔演讲稿
2014/05/08 职场文书
县政府办公室领导班子个人对照检查材料
2014/09/16 职场文书
银行委托书范本
2014/09/28 职场文书
学法用法心得体会(2016推荐篇)
2016/01/21 职场文书
五年级作文之成长
2019/09/16 职场文书
Python控制台输出俄罗斯方块移动和旋转功能
2021/04/18 Python
MySQL下载安装配置详细教程 附下载资源
2022/09/23 MySQL
keepalived + nginx 实现高可用方案
2022/12/24 Servers