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()方法,具體的我們下篇文章再講解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM