React中Ref 的使用方法详解


Posted in Javascript onApril 28, 2020

本文实例讲述了React中Ref 的使用方法。分享给大家供大家参考,具体如下:

React中Ref 的使用 React v16.6.3

在典型的React数据流中,props是父组件与其子组件交互的唯一方式。要修改子项,请使用new props 重新呈现它。但是,在某些情况下,需要在典型数据流之外强制修改子项。要修改的子项可以是React组件的实例,也可以是DOM元素。对于这两种情况,React都提供了api。

何时使用refs

refs有一些很好的用例:

  • 1.文本选择或媒体播放。
  • 2.触发势在必行的动画。
  • 3.与第三方DOM库集成。

避免将refs用于可以声明性地完成的任何操作。

*不要过度使用Refs

旧版API:字符串引用

如果您之前使用过React,那么您可能熟悉一个旧的API,其中ref属性是一个字符串"textInput",并且DOM节点被访问为this.refs.textInput。建议不要使用它,因为字符串引用有一些问题,被认为是遗留问题,很可能会在未来的某个版本中删除。

回调引用

当组件安装时,React将使用DOM元素调用ref回调,并在卸载时调用null。

在componentDidMount或componentDidUpdate触发之前,Refs保证是最新的.

class CustomTextInput extends React.Component {
 constructor(props) {
 super(props);

 this.textInput = null;

 this.setTextInputRef = element => {
  this.textInput = element;
 };

 this.focusTextInput = () => {
  // Focus the text input using the raw DOM API
  if (this.textInput) this.textInput.focus();
 };
 }

 componentDidMount() {
 // autofocus the input on mount
 this.focusTextInput();
 }

 render() {
 // Use the `ref` callback to store a reference to the text input DOM
 // element in an instance field (for example, this.textInput).
 return (
  <div>
  <input
   type="text"
   ref={this.setTextInputRef}
  />
  <input
   type="button"
   value="Focus the text input"
   onClick={this.focusTextInput}
  />
  </div>
 );
 }
}

refs例子--点击获取input焦点

class Example extends React.Component {
 handleClick() {
 // 使用原生的 DOM API 获取焦点
 this.refs.myInput.focus
 ();
 }
 render() {
 // 当组件插入到 DOM 后,ref 属性添加一个组件的引用于到 this.refs
 return (
  <div>
  <input type="text" ref="myInput" />
  <input
   type="button"
   value="点我输入框获取焦点"
   onClick={this.handleClick.bind(this)}
  />
  </div>
 );
 }
}

使用React.createRef()

React.createRef()React 16.3中引入的API。如果您使用的是早期版本的React,我们建议您使用回调引用。

创建React.createRef()

Refs是使用属性创建的,React.createRef()并通过ref属性附加到React元素。在构造组件时,通常将Refs分配给实例属性,以便可以在整个组件中引用它们。

class MyComponent extends React.Component {
 constructor(props) {
 super(props);
 this.myRef = React.createRef();
 }
 render() {
 return <div ref={this.myRef} />;
 }
}

访问ref

当ref被传递给元素时render,对该节点的引用变得可以在currentref 的属性处访问

const node = this.myRef.current;

ref的值根据节点的类型而有所不同

  • 当在refHTML元素上使用该属性时,ref在构造函数中创建的属性将React.createRef()接收底层DOM元素作为其current属性。
  • 在ref自定义类组件上使用该属性时,该ref对象将接收组件的已安装实例作为其current。

您可能无法ref在函数组件上使用该属性,因为它们没有实例。

class CustomTextInput extends React.Component {
 constructor(props) {
 super(props);
 // create a ref to store the textInput DOM element
 this.textInput = React.createRef();
 this.focusTextInput = this.focusTextInput.bind(this);
 }

 focusTextInput() {
 // Explicitly focus the text input using the raw DOM API
 // Note: we're accessing "current" to get the DOM node
 this.textInput.current.focus();
 }

 render() {
 // tell React that we want to associate the <input> ref
 // with the `textInput` that we created in the constructor
 return (
  <div>
  <input
   type="text"
   ref={this.textInput} />

  <input
   type="button"
   value="Focus the text input"
   onClick={this.focusTextInput}
  />
  </div>
 );
 }
}

current当组件安装时,React将为该属性分配DOM元素,并null在卸载时将其分配回。ref更新发生之前componentDidMount或componentDidUpdate生命周期方法。

无法在函数组件上使用ref属性

function MyFunctionComponent() {
 return <input />;
}

class Parent extends React.Component {
 constructor(props) {
 super(props);
 this.textInput = React.createRef();
 }
 render() {
 // This will *not* work!
 return (
  <MyFunctionComponent ref={this.textInput} />
 );
 }
}

**如果需要引用它,则应该将组件转换为类,就像您需要生命周期方法或状态时一样。
但是,只要引用DOM元素或类组件,就可以在函数组件中使用该ref属性:**

function CustomTextInput(props) {
 // textInput must be declared here so the ref can refer to it
 let textInput = React.createRef();

 function handleClick() {
 textInput.current.focus();
 }

 return (
 <div>
  <input
  type="text"
  ref={textInput} />

  <input
  type="button"
  value="Focus the text input"
  onClick={handleClick}
  />
 </div>
 );
}

将DOM引用公开给父组件

在极少数情况下,可能希望从父组件访问子节点的DOM节点。通常不建议这样做,因为它会破坏组件封装,但它偶尔可用于触发焦点或测量子DOM节点的大小或位置。

虽然可以向子组件添加引用,但这不是一个理想的解决方案,因为只能获得组件实例而不是DOM节点。此外,这不适用于功能组件。

如果使用React 16.3或更高版本,我们建议在这些情况下使用ref forwarding。引用转发允许组件选择将任何子组件的引用公开为自己的组件。可以在ref转发文档中找到有关如何将子DOM节点公开给父组件的详细示例。

如果您使用React 16.2或更低版本,或者您需要比ref转发提供的更多灵活性,您可以使用此替代方法并明确地将ref作为不同名称的prop传递。

如果可能,建议不要暴露DOM节点,但它可以是一个有用的逃生舱。请注意,此方法要求向子组件添加一些代码。如果您完全无法控制子组件实现,则最后一个选项是使用findDOMNode(),但不鼓励使用它StrictMode。

希望本文所述对大家react程序设计有所帮助。

Javascript 相关文章推荐
javascript去掉前后空格的实例
Nov 07 Javascript
DOM事件阶段以及事件捕获与事件冒泡先后执行顺序(图文详解)
Aug 18 Javascript
JS实现的表格操作类详解(添加,删除,排序,上移,下移)
Dec 22 Javascript
javascript图片切换综合实例(循环切换、顺序切换)
Jan 13 Javascript
jquery基础知识第一讲之认识jquery
Mar 17 Javascript
老生常谈原生JS执行环境与作用域
Nov 22 Javascript
Node.js获取前端ajax提交的request信息
Feb 20 Javascript
关于Javascript中document.cookie的使用
Mar 08 Javascript
vue中axios解决跨域问题和拦截器的使用方法
Mar 07 Javascript
vue自定义js图片碎片轮播图切换效果的实现代码
Apr 28 Javascript
JS如何实现封装列表右滑动删除收藏按钮
Jul 23 Javascript
详解Vue中的自定义指令
Dec 07 Vue.js
在Webpack中用url-loader处理图片和字体的问题
Apr 28 #Javascript
react PropTypes校验传递的值操作示例
Apr 28 #Javascript
vue 百度地图(vue-baidu-map)绘制方向箭头折线实例代码详解
Apr 28 #Javascript
Vue + Scss 动态切换主题颜色实现换肤的示例代码
Apr 27 #Javascript
浅析vue cli3 封装Svgicon组件正确姿势(推荐)
Apr 27 #Javascript
react组件基本用法示例小结
Apr 27 #Javascript
react基本安装与测试示例
Apr 27 #Javascript
You might like
Win7下手动安装apache2.2、php5.4笔记
2015/04/03 PHP
thinkphp的dump函数无输出实例代码
2016/11/15 PHP
javascript 跨浏览器开发经验总结(五) js 事件
2010/05/19 Javascript
javascript之typeof、instanceof操作符使用探讨
2013/05/19 Javascript
javascript闭包传参和事件的循环绑定示例探讨
2014/04/17 Javascript
Js Jquery创建一个弹出层可加载一个页面
2014/05/08 Javascript
jQuery实现table隔行换色和鼠标经过变色的两种方法
2014/06/15 Javascript
javascript面向对象快速入门实例
2015/01/13 Javascript
javascript手工制作悬浮菜单
2015/02/12 Javascript
js+HTML5基于过滤器从摄像头中捕获视频的方法
2015/06/16 Javascript
JavaScript文本框脚本编写的注意事项
2016/01/25 Javascript
关于JS中setTimeout()无法调用带参函数问题的解决方法
2016/06/21 Javascript
jQuery加载及解析XML文件的方法实例分析
2017/01/22 Javascript
JS数组求和的常用方法实例小结
2019/01/07 Javascript
详解Vue+ElementUI从零开始搭建自己的网站(一、环境搭建)
2019/04/30 Javascript
Vue.js标签页组件使用方法详解
2019/10/19 Javascript
微信小程序canvas开发水果老虎机的思路详解
2020/02/07 Javascript
Javascript原生ajax请求代码实例
2020/02/20 Javascript
Vue组件为什么data必须是一个函数
2020/06/11 Javascript
[03:28]2014DOTA2国际邀请赛 走近EG战队天才中单Arteezy
2014/07/12 DOTA
python实现的一个p2p文件传输实例
2014/06/04 Python
Python检测字符串中是否包含某字符集合中的字符
2015/05/21 Python
在Python程序和Flask框架中使用SQLAlchemy的教程
2016/06/06 Python
Python利用Beautiful Soup模块创建对象详解
2017/03/27 Python
python中强大的format函数实例详解
2018/12/05 Python
Jmeter调用Python脚本实现参数互相传递的实现
2021/01/22 Python
input file上传文件样式支持html5的浏览器解决方案
2012/11/14 HTML / CSS
html5中 media(播放器)的api使用指南
2014/12/26 HTML / CSS
基于HTML5 WebGL的3D机房的示例
2018/03/16 HTML / CSS
校企合作协议书
2014/04/16 职场文书
社团活动总结范文
2014/04/26 职场文书
社区文艺活动方案
2014/08/19 职场文书
2015年学生会干事工作总结
2015/04/09 职场文书
2015年度电厂个人工作总结
2015/05/13 职场文书
MySQL 8.0 Online DDL快速加列的相关总结
2021/06/02 MySQL
基于Python编写简易版的天天跑酷游戏的示例代码
2022/03/23 Python