React 中 Ref 引用

发布时间 2023-11-29 16:21:54作者: 背包の技术

不要因为别人的评价而改变自己的想法,因为你的生活是你自己的。

1. React 中 Ref 的应用

1.1 给标签设置 ref

给标签设置 ref,ref="username", 通过 this.refs.username 可以获取引用的标签,ref 可以获取到应用的真实 Dom 节点。但是 this.refs 已被废弃。

import React, { Component } from "react";

class App extends Component {
  render() {
    return (
      <div>
        <input ref="oref"/>
        <button onClick={ ()=>{ console.log("value:", this.refs.oref.value) } }>Add</button>
      </div>
    )
  }
}

export default App;

1.2 给组件设置 ref

同上标签设置 ref 给组件设置 ref 也保持一致,ref="username", 通过 this.refs.username 可以获取到组件对象。

1.3 新的语法设置 ref

通过定义一个引用属性 myRef = React.createRef(),通过 this.myRef.current 可以获取到标签的真实 Dom 节点以及对应的组件对象。

import React, { Component } from "react";

class App extends Component {

  myRef = React.createRef()

  render() {
    return (
      <div>
        <div>
          <input ref="oref"/>
          <button onClick={ ()=>{ console.log("value:", this.refs.oref.value) } }>Add1</button>
        </div>
        <div>
          <input ref={ this.myRef } />
          <button onClick={ ()=>{ console.log("value:", this.myRef.current.value) } }>Add2</button>
        </div>
      </div>
    )
  }
}

export default App;

2. 引用传送 forwardRef

引用传送(Ref forwarding)是一种通过组件向子组件自动传递引用 ref 并可以转发 ref 属性的技术。当父组件需要得到子组件的元素时,可以利用 forwardRef 来实现。

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

对于应用者的大多数组件来说没什么作用。但是对于有些重复使用的组件,可能有用。例如某些 input 组件,需要控制其 focus,本来是可以使用 ref 来控制,但是因为该 input 已被包裹在组件中,这时就需要使用 Ref forward 来透过组件获得input 的引用,可以透传多层。

应用场景:

ref 的作用是获取实例,可能是 DOM 实例,也可能是 ClassComponent 的实例。

为什么需要 forwardRef,我们看一个 React 报错:

Warning: Function components cannot be given refs. 
Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

大致的意思是,函数组件不能直接通过 useRef 引用,应该使用 React.forwardRef 对函数组件进行包裹在进行引用。

一个 Function Component,是没有实例的(PureComponent),此时用 ref 去传递会报错。

React.forwardRef 会创建一个 React 组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特别有用:

  • 转发 refs 到 DOM 组件;
  • 在高阶组件中转发 refs;

此时 React 会将外部 ref,当做参数进行传入,我们就可以将 ref 放入到我们要引用的对象上面。

注意: React 并没有将外部 ref 属性放入 props 中。

普通用法:

import React, { Component } from 'react'

export default class App extends Component {
  mytext=null
  render() {
    return (
      <div>
        <button type="button" onClick={()=>{
          console.log(this.mytext);
          this.mytext.current.focus()
          this.mytext.current.value="2222"
        }}>获取焦点</button>
        <Child callback={(el)=>{
          console.log(el);、
          //el是临时变量,用全局的去接这个值
          this.mytext=el
          //console.log(el.current);
        }}/>
      </div>
    )
  }
}

class Child extends Component {
  mytext = React.createRef();
  //组件渲染完了执行
  componentDidMount() {
    this.props.callback(this.mytext);
  }
  render() {
    return (
      <div style={{background:"yellow"}}>
        <input defaultValue="1111" ref={this.mytext}></input>
      </div>
    );
  }
}

使用 forwardRef:

import React, { Component,forwardRef } from 'react'

export default class App_forwardRef extends Component {
  mytext=React.createRef()
  render() {
    return (
      <div>
      <button type="button" onClick={()=>{
        console.log(this.mytext);
        this.mytext.current.value="2222"
      }}>获取焦点</button>
      <Child ref={this.mytext}/>
      </div>
    )
  }
}
// 这里Child是函数式组件
// 1、当我们试图给函数式组件给予ref属性的时候,会发现并不支持;
// 2、此时需要将子组件用forwardRef进行包裹,它的第二个参数即为我们所需要的元素,当拿到子组件元素的时候,则父组件可以利用此元素对子组件进行操作;
const Child=forwardRef((props,ref)=>{
    return (
      <div>
        <input defaultValue="11111" ref={ref}></input>
      </div>
    );
})