【一文一问】抓住两个思路,掌握React Ref

143 阅读2分钟

一,指向原生DOM

语法:

let myRef = React.createRef()

注意:函数组件和类组件皆可用

1,类组件示例

class Input extends React.Component{
  constructor(props){
    super(props)
    this.state={
     value:''
    }
    this.inputRef = React.createRef() // 1,创建ref
  }
 
  handleFocus=()=>{
    console.log('this.inputRef.current',this.inputRef.current )
    this.inputRef.current.focus() //3,指向input这个dom节点,调用focus方法
  }

  render(){
    return (
      <>
        <h1>Class Component</h1>
        <input ref={this.inputRef}/> //2,将ref挂到input上
        <button onClick={this.handleFocus}>click</button>
      </>
    )
  }
}

export default Input

效果:

image.png

2,函数组件示例

const Input = ()=>{
  let inputRef = React.createRef() // 1,创建ref
  const handleClick = ()=>{
    console.log('inputRef.current', inputRef.current)
    inputRef.current.focus() //3,指向input这个dom节点,调用focus方法
  }
  return(
    <>
      <h2>Functional Component</h2>
      <input ref={inputRef}/> // 2,将inputRef挂到input上
      <button onClick={handleClick}>click</button>
    </>
  )
}

效果:

image.png

二,指向类组件实例

注意:函数组件不可用

1,示例

//content.js 父组件
class Content extends React.Component{
  constructor(props){
    super(props)
    this.fatherRef = React.createRef() // 1,创建ref
  }
  handleClick=()=>{
    console.log('this.fatherRef.current',this.fatherRef.current)
    this.fatherRef.current.handleFocus()  // 3,调用子组件实例上的handleFocus,实现聚焦
  }
  
  render(){
    return (
      <>
        <h2>hello ref</h2>
        <button onClick={this.handleClick}>father click</button><br/>
        <Input ref={this.fatherRef} />  //2,将ref挂到子组件Input的实例上
       </>
    )
  }
}
// input.js 子组件
class Input extends React.Component{
  constructor(props){
    super(props)
    this.sonRef = React.createRef() // 1,创建ref
  }
  handleFocus=()=>{
    console.log('this.sonRef.current',this.sonRef.current )
    this.sonRef.current.focus() // 3, 指向input这个DOM节点,注意与父组件指向实例相区别
  }

  render(){
    return (
      <>
        <input ref={this.sonRef}/> // 2,将ref挂到input上
      </>
    )
  }
}

效果:注意看打印结果

image.png

2,错误示例:将ref挂在函数组件上

//content.js 父组件
class Content extends React.Component{
  constructor(props){
    super(props)
    this.state={
      
    }
    this.fatherRef = React.createRef()
  }
  handleClick=()=>{
    console.log('this.fatherRef.current',this.fatherRef.current)
    // this.fatherRef.current.handleFocus()
    this.fatherRef.current.focus()
  }
  
  render(){
    return (
      <>
        <h2>hello ref</h2>
        <button onClick={this.handleClick}>father click</button><br/>
        <Input ref={this.fatherRef} /> //将ref挂在函数组件Input上
       </>
    )
  }
}
// input.js 子组件
const Input = ()=>{
  return(
    <>
      <input/>
    </>
  )
}

效果:喜提报错

image.png 报错中提到React.forwardRef,这又是什么呢?

3,React.forwardRef——没有实例的函数组件也可以挂ref

官方解释要点:1,Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧。2,React.forwardRef 接受一个渲染函数。3,Ref 转发不仅限于 DOM 组件,你也可以转发 refs 到 class 组件实例中。

// content.js 父组件
class Content extends React.Component{
  constructor(props){
    super(props)
    this.fatherRef = React.createRef() //1,创建ref
  }
  handleClick=()=>{
    console.log('this.fatherRef.current',this.fatherRef.current)
    this.fatherRef.current.focus() 3,指向input这个DOM元素,调用focus方法
  }
  
  render(){
    return (
      <>
        <h2>hello ref</h2>
        <button onClick={this.handleClick}>father click</button><br/>
        <Input ref={this.fatherRef} /> 2,将ref挂在函数组件Input上
       </>
    )
  }
}

// input.js 子组件 调用React.forwardRef
const Input = React.forwardRef((props,fatherRef)=>(
  <>    //传参1:传来的props,传参2:父组件传过来的ref
    <input ref={fatherRef}/> //将fatherRef挂在input上,指向input这个DOM节点
  </>
))

欢迎留言,敬请批评指正噢~

参考文档

1,Refs 转发 – React (docschina.org)

2,Refs and the DOM – React (docschina.org)

3,【 最全react 教程 -- ref用法 和使用场景 】_哔哩哔哩_bilibili