react-refs转发

Refs转发

Ref转发是一项将ref自动地通过组件传递到其一子组件的技巧。对于大多数应用的组件来说,这通常是不需要的,但对于某些组件,尤其是可复用的组件库是很有用的。refs允许我们访问dom节点或者在react render函数中创建的react函数

转发Refs到DOM组件

考虑到渲染原生DOM的button的FancyButton组件

import React from 'react'
function FancyButton(props){
  return (
    <button className='FancyButton'>{props.children}</button>
  )
}

React组件隐藏其实现细节,包括其渲染结果,其他使用FancyButton的组件也不需要获取内部DOM原素button的ref。这很好,这防止组件过度依赖其他组件的DOM结构

虽然这种封装对类似FeedStory或者Comment这种应用组件是理想的,但是对于FancyButton或者MyTextInput这样的高复用的"叶"组件来说可能是不方便的。这些组件倾向于在整个应用中以一种类似常规的DOM button、input的方式被使用,并且访问其DOM节点对管理焦点,选中或动画来说是不可避免的

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

在下面的示例中,FancyButton使用React.forwardRef来获取传递给它的Ref,然后转发到它渲染的DOM button

const FancyButton = React.forwardRef((props,ref) =>
  (
    <button ref={ref} className='FancyButton'>{props.children}</button>
  )
)

function FancyCom () {
  const ref = React.createRef()
  console.log(ref)
  return (
    <FancyButton ref={ref} >Click me</FancyButton>
  )
}
export default  FancyCom

这样,使用FancyButton的组件可以获取底层dom button的节点的ref,并在必要时访问,就像其直接使用DOM的button一样

以下是对上述示例的逐步解释

  • 我们通过调用React.createRef创建了一个React Ref并将其赋值给ref变量
  • 我们通过指定的ref为jsx属性,将其向下传递给<FancyButton /ref={ref}>
  • React传递ref给fforwardRef内函数(props, ref) => ...作为其第二个参数
  • 我们向下转发该ref参数到<button ref={ref}>{props.children}<button>,将其指定为jsx属性
  • 当ref挂载完成,ref.current指向

Ref使用场景

在默写情况下,我们需要在典型的数据流之外强制的修改子组件,被修改的子组件可能是一个react组件的一个实例,也可能是一个dom元素

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

设置refs

createRef

支持函数组件和类组件内部使用

创建refs

使用React,createRef()创建ref,并通过ref属性附加在React元素上面,通常在构造函数中,将Refs分配给实例属性,以便在整个组件中引用

export default class MyInput extends React.Component{
  constructor (props) {
    super(props);
    this.inputRef = React.createRef(null)
  }
  componentDidMount () {
    this.inputRef && this.inputRef.current.focus()
  }
  render () {
    return (
      <input type="text" ref={this.inputRef}/>
    )
  }
}

ref的值根据节点类型的不同而有所不同

当ref的值是HTML元素的时候,构造函数中使用React.createRef()创建的ref接收底层dom元素作为其current属性

当ref属性用于自定义class组件时,ref对象接收组件挂载的实例作为其current属性

原文地址:https://www.cnblogs.com/dehenliu/p/13410904.html