React/Refs and this DOM
Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。
何时使用Refs
- 管理焦点,文本选择或媒体播放。
- 触发强制动画。
- 集成第三方 DOM 库。
避免使用 refs 来做任何可以通过声明式实现来完成的事情。(比如:避免在 Dialog
组件里暴露 open()
和 close()
方法,最好传递 isOpen
属性。)
创建 Refs
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} />;
- }
- }
访问 Refs
当 ref 被传递给 render
中的元素时,对该节点的引用可以在 ref 的 current
属性中被访问。
- const node = this.myRef.current;
ref 的值根据节点的类型而有所不同:
- 当
ref
属性用于 HTML 元素时,构造函数中使用React.createRef()
创建的ref
接收底层 DOM 元素作为其current
属性。 - 当
ref
属性用于自定义 class 组件时,ref
对象接收组件的挂载实例作为其current
属性。 - 你不能在函数组件上使用
ref
属性,因为他们没有实例。但是可以在函数组件内部使用ref
属性,只要它指向一个 DOM 元素或 class 组件
React 会在组件挂载时给 current
属性传入 DOM 元素,并在组件卸载时传入 null
值。ref
会在 componentDidMount
或 componentDidUpdate
生命周期钩子触发前更新。
将 DOM Refs 暴露给父组件
在极少数情况下,你可能希望在父组件中引用子节点的 DOM 节点。通常不建议这样做,因为它会打破组件的封装,但它偶尔可用于触发焦点或测量子 DOM 节点的大小或位置。
如果你使用 16.3 或更高版本的 React, 这种情况下我们推荐使用 ref 转发。
Refs转发
Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧。对于大多数应用中的组件来说,这通常不是必需的。但其对某些组件,尤其是可重用的组件库是很有用的。
Ref 转发是一个可选特性,其允许某些组件接收 ref
,并将其向下传递(换句话说,“转发”它)给子组件。
转发 refs 到 DOM 组件
在下面的示例中,FancyButton
使用 React.forwardRef
来获取传递给它的 ref
,然后转发到它渲染的 DOM button
:
- const FancyButton = React.forwardRef((props, ref) => (
- <button ref={ref} className="FancyButton">
- {props.children}
- </button>
- ));
- // 你可以直接获取 DOM button 的 ref:
- const ref = React.createRef();
- <FancyButton ref={ref}>Click me!</FancyButton>;
这样,使用 FancyButton
的组件可以获取底层 DOM 节点 button
的 ref ,并在必要时访问,就像其直接使用 DOM button
一样。
以下是对上述示例发生情况的逐步解释:
- 我们通过调用
React.createRef
创建了一个 React ref 并将其赋值给ref
变量。 - 我们通过指定
ref
为 JSX 属性,将其向下传递给<FancyButton ref={ref}>
。 - React 传递
ref
给forwardRef
内函数(props, ref) => ...
,作为其第二个参数。 - 我们向下转发该
ref
参数到<button ref={ref}>
,将其指定为 JSX 属性。 - 当 ref 挂载完成,
ref.current
将指向<button>
DOM 节点。
第二个参数 ref
只在使用 React.forwardRef
定义组件时存在。常规函数和 class 组件不接收 ref
参数,且 props 中也不存在 ref
。
Ref 转发不仅限于 DOM 组件,你也可以转发 refs 到 class 组件实例中。
回调 Refs
React 也支持另一种设置 refs 的方式,称为“回调 refs”。它能助你更精细地控制何时 refs 被设置和解除。
不同于传递 createRef()
创建的 ref
属性,你会传递一个函数。这个函数中接受 React 组件实例或 HTML DOM 元素作为参数,以使它们能在其他地方被存储和访问。
React 将在组件挂载时,会调用 ref
回调函数并传入 DOM 元素,当卸载时调用它并传入 null
。在 componentDidMount
或 componentDidUpdate
触发前,React 会保证 refs 一定是最新的。
过时 API:String 类型的 Refs
如果你之前使用过 React,你可能了解过之前的 API 中的 string 类型的 ref 属性,例如 "textInput"
。你可以通过 this.refs.textInput
来访问 DOM 节点。我们不建议使用它,因为 string 类型的 refs 存在 一些问题。它已过时并可能会在未来的版本被移除。
findDOMNode
是一个访问底层 DOM 节点的应急方案(escape hatch)。在大多数情况下,不推荐使用该方法,因为它会破坏组件的抽象结构。严格模式下该方法已弃用。
ReactDOM.findDOMNode(component)
如果组件已经被挂载到 DOM 上,此方法会返回浏览器中相应的原生 DOM 元素。此方法对于从 DOM 中读取值很有用,例如获取表单字段的值或者执行 DOM 检测(performing DOM measurements)。
大多数情况下,你可以绑定一个 ref 到 DOM 节点上,可以完全避免使用 findDOMNode。当组件渲染的内容为
null
或false
时,findDOMNode
也会返回null
。当组件渲染的是字符串时,findDOMNode
返回的是字符串对应的 DOM 节点。
从 React 16 开始,组件可能会返回有多个子节点的 fragment,在这种情况下,findDOMNode
会返回第一个非空子节点对应的 DOM 节点。
findDOMNode
只在已挂载的组件上可用(即,已经放置在 DOM 中的组件)。如果你尝试调用未挂载的组件(例如在一个还未创建的组件上调用render()
中的findDOMNode()
)将会引发异常。
findDOMNode
不能用于函数组件。
ReactDOM.unmountComponentAtNode(container)
从 DOM 中卸载组件,会将其事件处理器(event handlers)和 state 一并清除。如果指定容器上没有对应已挂载的组件,这个函数什么也不会做。如果组件被移除将会返回
true
,如果没有组件可被移除将会返回false
。
React/Refs and this DOM的更多相关文章
- React Refs
React Refs React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上. 这个特殊的属性允许你引用 render() 返回的相应的支撑实例( back ...
- React Refs All In One
React Refs All In One https://reactjs.org/docs/react-api.html#refs Ref https://reactjs.org/docs/refs ...
- [react] 什么是虚拟dom?虚拟dom比操作原生dom要快吗?虚拟dom是如何转变成真实dom并渲染到页面的?
壹 ❀ 引 虚拟DOM(Virtual DOM)在前端领域也算是老生常谈的话题了,若你了解过vue或者react一定避不开这个话题,因此虚拟DOM也算是面试中常问的一个点,那么通过本文,你将了解到如下 ...
- 深入理解react中的虚拟DOM、diff算法
文章结构: React中的虚拟DOM是什么? 虚拟DOM的简单实现(diff算法) 虚拟DOM的内部工作原理 React中的虚拟DOM与Vue中的虚拟DOM比较 React中的虚拟DOM是什么? ...
- React中的虚拟DOM
当组件当state和props发生变化当时候,组件当render函数就会重新执行,组件就会被重新渲染,react中实现这种重新渲染,他的性能是非常高的,因为他引入了一个虚拟Dom的概念,那么什么是虚拟 ...
- 谈谈Vue/React中的虚拟DOM(vDOM)与Key值
谈谈Vue/React中的虚拟DOM(vDOM)与Key值 一.DocumentFragment 在了解虚拟DOM前,先来了解DOM的一个对象属性--DocumentFragment. 在一次操作中, ...
- 简谈react中的虚拟DOM
相信你在看到此篇前也翻阅大量的对DOM的文章讲解和介绍 react中的虚拟DOM 此篇我尽量说人话(大白话),不然想必你在看到别的大神的文章早就懂了. 不说废话了,上干货. 1.首先简单对Html中的 ...
- 【Web技术】401- 在 React 中使用 Shadow DOM
本文作者:houfeng 1. Shadow DOM 是什么 Shadow DOM 是什么?我们先来打开 Chrome 的 DevTool,并在 'Settings -> Preferences ...
- React v16-alpha 从virtual dom 到 dom 源码简读
一.物料准备 1.克隆react源码, github 地址:https://github.com/facebook/react.git 2.安装gulp 3.在react源码根目录下: $npm in ...
随机推荐
- angular自定义组件
https://cli.angular.io/ 打开终端创建header组件: ng g component components/header import { Component, OnInit ...
- ASP程序中调用Now()总显示“上午”和“下午”,如何解决?
ASP程序中调用Now()总显示这样的格式:“2007-4-20 下午 06:06:38”,我要的正确格式为“2007-4-20 18:06:38”,我已经通过控制面板==>区域和语言选项==& ...
- VS2015 osgEarth 编译
E:\OpenSourceGraph\CURL_install\includeE:\GDAL\includeE:\Geos\geos_3_5_install\includeE:\OpenSourceG ...
- 编译freeglut
下载freeglut http://freeglut.sourceforge.net/ 1>------ 已启动生成: 项目: CallbackMaker, 配置: Debug x64 --- ...
- IFC数据模型构件控制
控制ifc构件的隐藏与显示.着色 osg::ref_ptr<osg::Geode> geode1 = new osg::Geode(); osg::ref_ptr<osg::Stat ...
- Python之queue模块以及生产消费者模型
队列 队列类似于一条管道,元素先进先出,进put(arg),取get() 有一点需要注意的是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态. 队列分类 队列有很多中,但都依赖 ...
- CentOS设置交换分区swap
环境查看 查看未设置交换分区之前 free -h 新加一块磁盘用于交换分区/dev/sdc 格式化 mkswap /dev/sdc 设置为交换分区 swapon /dev/sdc 再次查看 设置为重启 ...
- 用Python做一个简单的小游戏
学习总是枯燥的,对于Python小白的我来讲,更是乏味的.为了提高学习的兴趣,今天我就来写一个小程序练练手. 数字猜谜游戏相信大家都不陌生,A给出最小值最大值,B写一个该范围内的数,A猜测写下的是多少 ...
- Ubuntu linux 下的基本操作
防火墙相关: 关闭防火墙: ufw disable
- C#实现动态发布IIS站点帮助类
准备工作: 1.引用 System.DirectoryServices 系统程序集 2.引用 Microsoft.Web.Administration 程序集,类库位置在 C:\Windows\Sys ...