06_使用refs获取DOM/组件实例

245 阅读2分钟

在React中,通常情况下不建议直接操作原生DOM,但是某些特殊的情况下,确实需要获取DOM进行操作

  • 管理焦点,文本选择或者媒体播放
  • 触发强制动画
  • 集成第三方DOM库

在React中使用ref来获取DOM对象和组件实例,ref的值根据获取的节点的类型有所不同

  • 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收 DOM 元素作为其 current 属性;
  • 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性;
  • 不能在函数组件上使用 ref 属性,因为它们没有实例;但是通过React.forwardRef将ref转发给函数式组件中的某个DOM元素
  • 当需要一个不会因为组件的重新渲染而变化的对象时,就可以使用fef

获取DOM

  • 方式一:在React元素上绑定ref属性,传入一个字符串,

    • 通过 this.refs.传入的字符串 获取对应的元素 (已过时)
  • 方式二:在React元素上绑定ref属性,传入由React.createRef()创建的对象

    • 创建的ref对象中有一个current属性就是对应的DOM对象
  • 方式三:在React元素上绑定ref属性,传入一个回调函数,

    • 该函数会在DOM被挂载时进行回调,这个函数会传入一个元素对象,将这个对象进行保存
import React, { PureComponent, createRef } from 'react'

export class App extends PureComponent {
  constructor() {
    super()
    this.state = {}

    this.titleRef = createRef()
    this.titleEl = null
  }

  getNativeDOM() {
    // 1.方式一: ref属性绑定一个ref字符串
    console.log(this.refs.ycl)

    // 2.方式二: ref属性绑定 提前创建好的ref对象, createRef()
    console.log(this.titleRef.current)

    // 3.方式三: ref属性绑定一个回调函数, 在对应的元素被渲染之后, 回调函数被执行, 并且将元素传入
    console.log(this.titleEl)
  }

  render() {
    return (
      <div>
        <h2 ref="ycl">Hello World</h2>
        <h2 ref={this.titleRef}>你好,React</h2>
        <h2 ref={el => this.titleEl = el}>你好啊, World</h2>
        <button onClick={e => this.getNativeDOM()}>获取DOM</button>
      </div>
    )
  }
}

export default App

获取组件实例

import React, { PureComponent, createRef } from 'react'

class HelloWorld extends PureComponent {
  test() {
    console.log("-----test-----")
  }

  render() {
    return <h1>Hello World</h1>
  }
}

export class App extends PureComponent {
  constructor() {
    super()

    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

ref的转发

React.forwardRef() 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。

import React, { PureComponent, createRef, forwardRef } from 'react'

const HelloWorld = forwardRef(function(props, ref) {
  return (
    <div>
      <h1 ref={ref}>Hello World</h1>
      <p>哈哈哈</p>
    </div>
  )
})

export class App extends PureComponent {
  constructor() {
    super()

    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