React 通过ref获取DOM对象或者子组件实例的用法

在class组件中我们会用render返回一系列的组件或者DOM节点,有时我们需要获取某一个DOM节点或者子组件的实例,然后去对他进行一些手动的操作,我们可以在componentDidMount生命周期函数内通过DOM选择器来获取对应的DOM对象,但是这不是很方便,因为很多需要都需要我们保存对应的DOM对象的引用,管理起来也有点麻烦。

我们可以用ref来获取某个子节点的实例,然后通过当前class组件实例的一些特定属性来直接获取子节点实例。(vue里也有一个ref属性,通过this.$refs来获取DOM实例,两个差不多的)

ref有三种实现方法:

  • 字符串格式       ;字符串格式,这是React16版本之前用得最多的。         ;例如:<p ref="info">span</p>
  • 函数格式       ;ref对应一个方法,该方法有一个参数,也就是对应的节点实例   ;例如:<p ref={ele => this.info = ele}></p>
  • createRef方法     ;React16提供的一个API,使用React.createRef()来实现         

方法一 字符串格式

我们可以在render函数内返回的jsx代码片段中,给某个DOM节点或者子组件设置一个ref属性,传递一个字符串,这样当当前组件渲染完成后,我们可以通过当前class组件实例上的refs属性获取对应的一个DOM对象或者子组件实例

比如jsx中有这样的一个代码片段:<p ref="info">span</p>,之后我们就可以通过this.refs.info获取到该p元素渲染后生成的DOM实例了。

举个例子:

<div id="root"></div>    
<script type="text/babel">            
  class RefDemo extends React.Component{
    state = {no:1}
    componentDidMount = ()=>{ this.refs.info.textContent = "no = "+this.state.no }      //组件挂载完成后设置this.ref.info这个DOM节点的textContext

    test=()=>{ this.refs.info.textContent= "no = "+ ++this.state.no }                   //点击测试按钮后也修改this.ref.info这个DOM节点的textContext
    
    render(){
      return (
        <div>
          <button onClick={this.test}>测试</button>
          <p ref="info"></p>
        </div>
      )
    }
  }
  ReactDOM.render(<RefDemo></RefDemo>,root)
</script>

效果如下:

 writer by:大沙漠 QQ:22969969

初始化时在componentDidMount生命周期函数内通过this.refs.info获取到p元素的节点,之后设置它的textContext属性,另外在测试按钮上也绑定了一个test属性,每次店家时递增this.state.no,并设置在this.refs.info这个DOM节点上,也就是p节点对象了。

方法二 函数格式

上面例子里符串格式的ref在内部会转换为一个函数格式,我们也可以直接将ref属性的值设置为一个函数,该函数可以传入一个参数,值是当前的DOM对象实例,比如:<p ref={ele => this.info = ele}></p>,这样我们在当前class组件内可以直接通过this.info获取到这个P元素的DOM对象实例了。

我们改写一下上面的例子,用函数格式来写一下,如下:

<div id="root"></div>    
<script type="text/babel">            
  class RefDemo extends React.Component{
    state = {no:1}
    componentDidMount = ()=>{ this.info.textContent = "no = "+this.state.no }

    test=()=>{ this.info.textContent= "no = "+ ++this.state.no }

    render(){
      return (
        <div>
          <button onClick={this.test}>测试</button>
          <p ref={ele => this.info = ele}></p>                                  //这里以函数的形式来写,在其它逻辑内只需通过this.info就可以获取这个p节点实例了
        </div>
      )
    }
  }
  ReactDOM.render(<RefDemo></RefDemo>,root)
</script>

运行的效果和第一个例子是一样了,就不截图了。

方法三 createRef方法

 createRef是React16新增的一个API,也是用于设置ref的,使用时,我们需要先执行

React.createRef()

执行后将返回一个{current: null}这样的对象,我们在jsx内将React.createRef()的返回值作为值设置在一个DOM节点的ref属性上,渲染后该DOM对象就会保存到React.createRef()返回的对象里的current属性上了。

还是改写一下第一个例子,我们用createRef方法来写一下,如下:

<div id="root"></div>    
<script type="text/babel">            
  class RefDemo extends React.Component{
    state = {no:1}
    domp = React.createRef();                                                             //执行React.createRef()返回一个{current:null}对象

    componentDidMount = ()=>{ this.domp.current.textContent = "no = "+this.state.no }

    test=()=>{ this.domp.current.textContent= "no = "+ ++this.state.no }

    render(){
      return (
        <div>
          <button onClick={this.test}>测试</button>
          <p ref={this.domp}></p>                                                         //设置ref属性,值直接指向React.createRef()的返回值即可,也就是当前的domp属性,之后在其它地方可以直接使用this.domp.current获取这个P实例了
        </div>
      )
    }
  }
  ReactDOM.render(<RefDemo></RefDemo>,root)
</script>

运行的效果和第一个例子也是一样,这里也不贴截图了,如果把ref设置在一个子节点组件上,则获取的是组件实例。

除了普通DOM节点或自组件的节点外,如果我们在jsx代码里引用了一个函数组件,由于在React当中函数组件也是返回jsx的,本身是没有实例的,因此我们设置ref属性获取到的值是为空的,此时可以用React.forwardRef()来解决,React.forwardRef也是用到了createRef()方法,具体的我们下篇文章再讲解。

posted @ 2020-04-20 06:37  大沙漠  阅读(13299)  评论(0编辑  收藏  举报