React中的组件实例对象的Refs属性

108 阅读3分钟
  • ref生成的是一个指针,指向了真实的DOM,
  • ref作用:是组件实例对象中的一个属性,值是一个对象,只需要给VDOM添加ref属性即可生成ref的指向,指向该DOM,类似于原生js中通过id获取节点。

何时使用Refs

下面有一些正好使用refs的场景:

  • 处理foucs、文本选择或媒体播放
  • 触发强制动画
  • 集成第三方DOM库
  • 如果可以通过声明式实现,就尽量避免使用refs。
  • 不要过度使用refs。
  • 你可能首先会想到在你的应用程序中使用refs来更新组件。如果是这种情况,请花一点时间,更多的关注在组件层中使用state。在组件层中,通常较高级别的state更为清晰。

使用Ref注意以下三点

  • Ref所指向的节点可以是dom节点,也可以是类组件。
  • 但是Ref属性指向的节点不能是函数组件(无状态组件)
  • 因为我们通过ref获得的组件,包含了生命周期和state,因此ref所指向的组件不可以是函数组件

字符串形式的ref

  1. 直接修改了真实节点去做操作。可以给每个元素添加ref属性,refs里就存了相应的节点。但不要过多使用。
  2. 该形式是把真实节点存到了refs身上
export default class App extends Component {
  render() {
    console.log(this)
    return (
      <div>
        <h1 onClick={this.changeDiv}>这是最上层组件</h1>
        <div ref="nh">你好</div>
      </div>
    )
    
  }
  changeDiv =() => {
    this.refs.nh.innerHTML="hello"
  }
}

回调函数形式的ref

  1. 在初始化的时候或更新组件就会调用该回调函数,由React调用,回调函数接收一个形参,形参就是当前节点对象,并且这个形参是一个真是节点。我们将得到的节点对象挂载到组件实例对象上。
  2. 该形式是把真是节点存到了组件实例对象的属性上,没有存到refs上。
export default class AppFn extends Component {
  render() {
    return (
      <div>
        <h1 onClick={this.hande}>这是顶层组件</h1>
        <div ref={c => this.myEle = c}>你好</div>
      </div>
    )
  }
  hande=()=>{
    this.myEle.style.background="#f00"
    console.log(this)
  }
}

  • 官方指出,如果ref回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数null,然后第二次会传入参数DOM元素。这是因为在每次渲染时会创建一个新的函数实力,所以React清空旧的ref并设置新的。
  • 为了保证更新之后得到的是更新之后的dom所以会先将该回调函数的参数赋值成null,依次保证每次都将之前的清除掉了。
  • 通过ref的回调函数定义成class的绑定函数的方式可以避免上述问题,到那时大多数情况下它是无关紧要的。

React.createRef()

注意:

  1. 一个React.createRef()只能存一个标记,把该标记作为组件实例对象的属性,与ref进行关联。
  2. 想要读取节点,必须通过current
export default class AppFn extends Component {
    myRef=React.createRef();
  render() {
    return (
      <div>
        <h1 onClick={this.hande}>这是1顶层组件,点击我有惊喜</h1>
        <div ref={this.myRef}>你好</div>
      </div>
    )
  }
  hande=()=>{
    this.myRef.current.style.backgroundColor="#fcc"
  }
}

forwardRef(作用:用来访问子组件的节点)

  • 通过React16.3中的forwarding refs可以使得在负组件中可以得到子组件的dom节点。
  • forwarding refs中提供了一个React.forwardRef()方法来创建组件,在React.forwardRef的方法中传递了参数ref,通过这个ref可以指向具体的某一个dom节点。
  • 具体的指向流程为:
  • 父组件myRef——React.forwardRef中的实参——通过forwardRef方法创建的子组件中的Ref——指向子组件中的某一个don节点。