17.React获取DOM的方式
3. 获取DOM方式refs
-
3.1. 如何使用Ref
-
- 在React的开发模式中,通常情况下不需要、也不建议直接操作原生DOM,但是某些特殊的情况,确实需要获取到DOM进行某些操作;
- 1.1. 管理焦点,文本选择或媒体播放;
- 1.2. 触发强制动画;
- 1.3. 集成第三方DOM库;
- 1.4. 我们可以通过refs获取DOM;
-
- 如何创建refs来获取对应的DOM呢?目前有三种方式:
- 2.1. 方式一: 在React元素上绑定一个ref字符串(这种方式获取ref元素会被废弃,
不推荐使用) - 2.2. 方式二:
提前创建好ref对象,createRef(), 将创建出来的对戏那个绑定到元素上(推荐使用这种方式) - 2.3. 方式三:
传入一个回调函数,在对应的元素被渲染之后,回调函数被执行,并且将元素传入 - 2.4. 示例代码如下:
import React, { PureComponent, createRef } from 'react'export class App extends PureComponent {constructor() {super()this.state = {}// 1. 创建的ref不涉及页面更新的东西,不涉及到渲染的东西this.titleRef = createRef()this.titleEl = null}getNativeDom () {// 不建议这样拿原生dom// const h2El = document.querySelector('h2')// 1. 方式一: 在React元素上绑定一个ref字符串(这种方式获取ref元素会被废弃,不推荐使用)// console.log(this.refs.why)// 2. 方式二: 提前创建好ref对象,createRef(), 将创建出来的对戏那个绑定到元素上(推荐使用这种方式)// console.log(this.titleRef.current)// 3. 方式三: 传入一个回调函数,在对应的元素被渲染之后,回调函数被执行,并且将元素传入console.log(this.titleEl)}render() {return (<div><h2 ref='why'>Hello World</h2><div ref={this.titleRef}>你好啊,李银河</div>{/* 传入一个函数,当元素渲染出来之后自动回调这个函数,回调函数时并把元素作为参数传递给这个函数 */}<div ref={el => this.titleEl = el }>你好啊,世界</div><button onClick={(e) => this.getNativeDom()}>获取ref元素</button></div>)}}export default App
-
-
3.2. ref获取类组件实例
-
- 类组件的ref获取方式和绑定元素类似,通过ref属性绑定组件实例
-
- 示例代码如下:
import React, { PureComponent, createRef } from 'react'export class HelloWorld extends PureComponent {test () {console.log('------')}render() {return (<div><h2>Hello World!</h2></div>)}}export class App extends PureComponent {constructor() {super()this.state = {}// 1. 创建的ref不涉及页面更新的东西,不涉及到渲染的东西this.hwRef = createRef()}getComponent () {console.log(this.hwRef.current)this.hwRef.current.test()}render() {return (<div><HelloWorld ref={this.hwRef} /><button onClick={(e) => this.getComponent()}>获取组件实例</button></div>)}}export default App
-
-
3.3. ref获取函数组件(ref的转发)
-
- 在前面我们学习ref时讲过,ref不能应用于函数式组件;
- 1.1. 因为函数式组件没有实例,所以不能获取对应的组件对象
-
- 但是,在开发中我们可能想要获取函数式组件中某个元素的DOM,这个时候我们应该如何操作呢?
- 方式一: 直接传入ref属性(错误的做法)
- 方式二: 通过forwardRef()高阶函数
-
- 示例代码如下:
import React, { PureComponent, createRef, forwardRef } from 'react'const HelloWorld = forwardRef (function (props, ref) {// 1. 在前面学习的ref,ref不能应用于函数式组件// - 1.1. 函数式组件没有实例,所以不能获取对应的组件对象;// 2. 通过forwardRef高阶函数;return (<div><h2 ref={ref}>Hello World!</h2><p>哈哈哈</p></div>)})export class App extends PureComponent {constructor() {super()this.state = {}// 1. 创建的ref不涉及页面更新的东西,不涉及到渲染的东西this.hwRef = createRef()}getComponent () {console.log(this.hwRef.current)}render() {return (<div><HelloWorld ref={this.hwRef} /><button onClick={(e) => this.getComponent()}>获取函数组件实例</button></div>)}}export default App
-
-
3.4. ref的类型
-
- ref的值根据节点的类型而有所不同
- 1.1. 当ref属性用于HTML元素时,构造函数中使用React.createRef()创建的ref接受底层DOM元素作为其current属性
- 1.2. 当ref属性用于自定义class组件时,ref对象接收组件的实例作为其current属性
- 1.3. 不能在函数组件上使用ref属性,因为他们没有实例
-
- 函数组件是没有实例的,所以无法通过ref获取他们的实例:
- 2.1. 但是某些时候,我们可能想要获取函数式组件中的某个DOM元素;
- 2.2. 这个时候我们可以通过React.forwardRef(), 当ref属性用于通过forwardRef转发的函数式组件时,ref对象接收组件内部转发的具体元素或组件实例作为其current属性。
- 2.3. 后面还会记录到hooks中如何使用ref;
-
