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 相关文章推荐
IE和FireFox(FF)中js和css的不同
Apr 13 Javascript
JavaScript自定义事件介绍
Aug 29 Javascript
JS创建自定义表格具体实现
Feb 11 Javascript
js动态生成Html元素实现Post操作(createElement)
Sep 14 Javascript
JS实现超精简的链接列表在固定区域内滚动效果代码
Nov 04 Javascript
JS 实现随机验证码功能
Feb 15 Javascript
vue 2.0 购物车小球抛物线的示例代码
Feb 01 Javascript
微信web端后退强制刷新功能的实现代码
Mar 04 Javascript
微信小程序之swiper轮播图中的图片自适应高度的方法
Apr 23 Javascript
Vue.js 时间转换代码及时间戳转时间字符串
Oct 16 Javascript
微信小程序如何实现精确的日期时间选择器
Jan 21 Javascript
VUE项目axios请求头更改Content-Type操作
Jul 24 Javascript
详解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在Web开发领域的优势
2006/10/09 PHP
php XMLWriter类的简单示例代码(RSS输出)
2011/09/30 PHP
PHP实现异步调用方法研究与分享
2011/10/27 PHP
使用Appcan客户端自动更新PHP版本号(全)
2015/07/31 PHP
使用JavaScript创建新样式表和新样式规则
2016/06/14 PHP
jquery 模拟雅虎首页的点击对话框效果
2010/04/11 Javascript
JavaScript中各种编码解码函数的区别和注意事项
2010/08/19 Javascript
jQuery根据ID获取input、checkbox、radio、select的示例
2014/08/11 Javascript
jquery操作select取值赋值与设置选中实例
2017/02/28 Javascript
详谈javascript精度问题与调整
2017/07/08 Javascript
js实现图片放大展示效果
2017/08/30 Javascript
vue中el-upload上传图片到七牛的示例代码
2018/10/19 Javascript
vue v-for循环重复数据无法添加问题解决方法【加track-by='索引'】
2019/03/15 Javascript
js定义类的方法示例【ES5与ES6】
2019/07/30 Javascript
jQuery实现可以扩展的日历
2020/12/01 jQuery
[08:29]DOTA2每周TOP10 精彩击杀集锦vol.7
2014/06/25 DOTA
[32:36]完美世界DOTA2联赛PWL S3 LBZS vs CPG 第二场 12.12
2020/12/16 DOTA
[01:23:45]DOTA2-DPC中国联赛 正赛 CDEC vs Dragon BO3 第一场 1月22日
2021/03/11 DOTA
Python实现LRU算法的2种方法
2015/06/24 Python
Scrapy的简单使用教程
2017/10/24 Python
Python实现base64编码的图片保存到本地功能示例
2018/06/22 Python
python实现windows壁纸定期更换功能
2019/01/21 Python
python语言的优势是什么
2020/06/17 Python
全球知名提供各类营养保健品的零售商:Vitamin Shoppe
2016/10/09 全球购物
新英格兰最大的特色礼品连锁店:The Paper Store
2018/07/23 全球购物
经典C++面试题一
2016/11/06 面试题
中介公司区域经理岗位职责范本
2014/03/02 职场文书
经营管理策划方案
2014/05/22 职场文书
合伙经营协议书范本
2014/09/13 职场文书
商务邀请函
2015/01/30 职场文书
埃及王子观后感
2015/06/16 职场文书
小学数学国培研修日志
2015/11/13 职场文书
python实现网络五子棋
2021/04/11 Python
Java循环队列与非循环队列的区别总结
2021/06/22 Java/Android
python lambda 表达式形式分析
2022/04/03 Python
我收到了德劲DE1107
2022/04/05 无线电