React中 ref的使用和转发forwardRef

ref

reference: 引用

1、场景:希望直接使用dom元素中的某个方法,或者希望直接使用自定义组件中的某个方法

  1. ref作用于内置的html组件,得到的将是真实的dom对象

    import React , {Component}  from"react";
    export default class MyRef extends Component {
        getFac= (e)=> {
            this.refs.input.focus()
        }
        render(){
            return (
                <div>
                    <input type="text" ref="input" />
                    <button onClick={this.getFac}>聚焦</button>
                </div>
            ) 
        }
    }
    
  2. ref作用于类组件,得到的将是类的实例

    //功能 通过ref 获得的是一个 对象,然后调用对象的方法。
    
    import React , {Component}  from"react";
    class Test extends Component {
        myMethod() {
            console.log("这是Test的函数")
        }
        render() {
            return (
                <div></div>
            )
        }
      }
    
    
    export default class MyRef extends Component {
        getFac= (e)=> {
            this.refs.input.focus();
            this.refs.testComp.myMethod();   // 这里是调用类的方法
           
        }
        render(){
            return (
                <div>
                    <Test ref="testComp"></Test>
                    <input type="text" ref="input" />
                    <button onClick={this.getFac}>聚焦</button>
                </div>
            ) 
        }
    }
    
  3. ref不能作用于函数组件

    • 给函数组件 ref 没有用,因为没有意义,我们并不能通过函数得到什么,给类组件得到一个对象,给react元素,得到的DOM 对象,即使给了函数组件ref ,使用时会报错,(不能使用ref)
    • 函数组件里面的react 元素是可以使用的。

2、ref不再推荐使用字符串赋值,字符串赋值的方式将来可能会被移出

  • 主要原因是因为效率问题,不够灵活。

  • 目前,ref推荐使用对象或者是函数

对象

通过 React.createRef 函数创建

export default class MyRef extends Component {

    constructor(props) {
        super(props);
        this.test = React.createRef();   //创建一个 ref 对象
       // 这个对象 也就是  { current : null}  那么就可以通过 { current : null} 替换 React.createRef() 也是可以的。
    }
    getFac= (e)=> {
        console.log(this.test)
        this.test.current.focus();
    }
    render(){
        return (
            <div>
                
                <input type="text" ref={this.test} />
                <button onClick={this.getFac}>聚焦</button>
            </div>
        ) 
    }
}

函数

函数的调用时间:

  1. componentDidMount的时候会调用该函数
    1. 在componentDidMount事件中可以使用ref
  2. 如果ref的值发生了变动(旧的函数被新的函数替代),分别调用旧的函数以及新的函数,时间点出现在componentDidUpdate之前
    1. 旧的函数被调用时,传递null
    2. 新的函数被调用时,传递对象
  3. 如果ref所在的组件被卸载,会调用函数

谨慎使用ref (违背react 的哲学理念,是一种反模式)

能够使用属性和状态进行控制,就不要使用ref。

  1. 调用真实的DOM对象中的方法 (如 vedio)
  2. 某个时候需要调用类组件的方法

3-4、ref转发

Ref 转发是一个可选特性,其允许某些组件接收 ref,并将其向下传递(换句话说,“转发”它)给子组件。

forwardRef

import React, { Component } from 'react'

function A(props,ref) {   // 第二个参数就是转发的得到的ref
    console.log(ref)
    return(
        <div ref={ref}>
   
        </div>
    )
}
const NewA = React.forwardRef(A)  //进行转发
export default class RefTest extends Component {
    ARef = React.createRef();
    render() {
        return (
            <div>
                <NewA ref={this.ARef}/>
            </div>
        )
    }
}

forwardRef方法:

  1. 参数,传递的是函数组件,不能是类组件,并且,函数组件需要有第二个参数来得到ref

    • 如果实在想通过类组价传递ref , 那么需要通过 prop 传递

      import React, { Component } from 'react'
      class A extends Component {
         render(){
             return(
                 <h1 ref={this.props.refA}>ddd</h1>
             )
           }
      }
      export default class RefTest extends Component {
          ARef = React.createRef();
          render() {
              return (
                  <div>
                      <A refA = {this.ARef}></A>   // 通过属性的来传递
                  </div>
              )
          }
      }
      
      
    • 也可以通过转发,但是需要一个中间层,这个中间层就是一个函数组件。

      import React, { Component } from 'react'
      class A extends Component {
         render(){
             return(
                 <h1 ref={this.props.refA}>ddd</h1>
             )
           }
      }
      const NewA = React.forwardRef((props,ref)=>{
          return (
              <A {...props} refA = {ref}></A>   //原理也是通过传递 props
          )
      })
      export default class RefTest extends Component {
          ARef = React.createRef();
          render() {
              return (
                  <div>
                      {/* <NewA ref={this.ARef}/> */}
                      <NewA ref={this.ARef}></NewA>   //这种方法 就可以使用 ref 
                  </div>
              )
          }
      }
      
      
  2. 返回值,返回一个新的组件

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值