React ref屬性


簡單來說,ref就是用來獲取真實dom元素或者是組件實例的屬性。

1. 創建和訪問

ref 的值根據節點的類型而有所不同:

  • 當 ref 屬性用於 HTML 元素時,構造函數中使用 React.createRef() 創建的 ref 接收底層 DOM 元素作為其 current 屬性。
  • 當 ref 屬性用於自定義 class 組件時,ref 對象接收組件的掛載實例作為其 current 屬性。
  • 不能在函數組件上使用 ref 屬性,因為他們沒有實例。若是想用需要經過特殊處理

1.1 ref=字符串 (已經廢棄)

class Cualculator extends React.Component { add =() => { let num1 = parseInt(this.refs.num1.value) let num2 = parseInt(this.refs.num2.value) let result = num1 +num2 this.refs.result.value = result } render() { return ( <div>
        <input ref="num1" />+<input ref="num2"/><button onClick={this.add}>=</button><input ref="result"/>
      </div>
 ) } }
 * num1:對應真實dom num1
 * num2:對應真實dom num2

1.2 ref=函數 (不推薦)

class Cualculator extends React.Component { add =() => { let num1 = parseInt(this.num1.value) let num2 = parseInt(this.num2.value) let result = num1 +num2 this.result.value = result } //ref值是一個函數的時候,此函數會在虛擬dom轉為真實dom插入也買你之后執行,參數就是真實dom
 render() { return ( <div>
        <input ref={instance => this.num1 = instance} />+<input ref={instance => this.num2 = instance}/><button onClick={this.add}>=</button><input ref={instance => this.result = instance}/>
      </div>
 ) } }

1.3 ref = React.createRef() (推薦使用)

通過React.createRef() 創建的ref屬性有以下幾個特點:

當 ref 被傳遞給 render 中的元素時,對該節點的引用可以在 ref 的 current 屬性中被訪問。

  • 當 ref 屬性用於 HTML 元素時,構造函數中使用 React.createRef() 創建的 ref 接收底層 DOM 元素作為其 current 屬性。
  • 當 ref 屬性用於自定義 class 組件時,ref 對象接收組件的掛載實例作為其 current 屬性。
  • 不能在函數組件上使用 ref 屬性,因為他們沒有實例。若是想用需要經過特殊處理

1.3.1 Html元素

class Cualculator extends React.Component { constructor(){ super() this.num1 = React.createRef() //{current:null} current在虛擬dom轉為真實dom插入頁面之后變成真實dom
    this.num2 = React.createRef() //{current:null} current在虛擬dom轉為真實dom插入頁面之后變成真實dom
    this.result = React.createRef() //{current:null} current在虛擬dom轉為真實dom插入頁面之后變成真實dom
 } add =() => { let num1 = parseInt(this.num1.current.value) let num2 = parseInt(this.num2.current.value) let result = num1 +num2 this.result.current.value = result } //ref值是一個函數的時候,此函數會在虛擬dom轉為真實dom插入頁面之后執行,參數就是真實dom
 render() { return ( <div>
        <input ref={this.num1} />+<input ref={this.num2}/>
        <button onClick={this.add}>=</button>
        <input ref={this.result}/>
      </div>
 ) } } ReactDOM.render(<Cualculator></Cualculator>,document.getElementById('root'))

dom元素作為current屬性的值

1.3.2 class組件

class UserName extends React.Component{ constructor(){ super() this.inputRef = React.createRef() } render(){ return ( <input ref={this.inputRef}></input>
 ) } } class Form extends React.Component{ constructor(){ super() this.username = React.createRef() //this.username 就是UserName組件的實例 this.username.current = new UserName()
 } getFocus = () => { this.username.current.inputRef.current.focus() //this.username.current.inputRef.current 獲取到組件對應的真實dom節點 就是 input框
 } render(){ return ( <form>
        <UserName ref={this.username}/>
        <button type="button" onClick={this.getFocus}>讓用戶名獲得焦點</button>
      </form>
 ) } }

組件的實例等於current屬性的值

1.3.3 函數組件

ref React.createRef()會獲取到一個真實dom或者是一個組件實例對象 但是函數組件沒有實例,那怎么獲取函數組件的ref屬性,這個時候就需要特殊處理
function UserName(props,ref) { return <input ref={ref}></input>
} const ForwordUsername = React.forwardRef(UserName) 
 class Form extends React.Component{ constructor(){ super() this.username = React.createRef() //this.username 就是ForwordUsername組件的實例 this.username.current = new ForwordUsername()
 } getFocus = () => { this.username.current.focus() //this.username.current.inputRef.current 獲取到組件對應的真實dom節點 就是 input框
 } render(){ return ( <form>
        <ForwordUsername ref={this.username}/>
        <button type="button" onClick={this.getFocus}>讓用戶名獲得焦點</button>
      </form>
 ) } }
React.forwardRef會穿透UserName組件,獲取到input的真實dom元素。

1.4 React.forwardRef()的底層實現

function UserName(props,ref) { return <input ref={ref}></input>
} 
function forwardRef (functionComponent) { return class extends React.Component { render() { return functionComponent(this.props,this.props.ref2) } } } const ForwordUsername = forwardRef(UserName) //React.forwardRef返回一個類組件,將這個類組件傳給
 class Form extends React.Component{ constructor(){ super() this.username = React.createRef() //this.username 就是UserName組件的實例 this.username.current = new UserName()
 } getFocus = () => { this.username.current.focus() //this.username.current.inputRef.current 獲取到組件對應的真實dom節點 就是 input框
 } render(){ return ( <form>
        <ForwordUsername ref2={this.username}/>
        <button type="button" onClick={this.getFocus}>讓用戶名獲得焦點</button>
      </form>
 ) } }

它是將函數組件轉換成了類組件,當然也可以直接返回一個轉化之后的函數組件

function UserName(props) { return <input ref={props.ref2}></input>
} //函數組件沒有this,可以通過
function forwardRef (functionComponent) { return props => functionComponent(props,props.ref2) } const ForwordUsername = forwardRef(UserName) //React.forwardRef返回一個類組件,將這個類組件傳給
 class Form extends React.Component{ constructor(){ super() this.username = React.createRef() //this.username 就是UserName組件的實例 this.username.current = new UserName()
 } getFocus = () => { this.username.current.focus() //this.username.current.inputRef.current 獲取到組件對應的真實dom節點 就是 input框
 } render(){ return ( <form>
        <ForwordUsername ref2={this.username}/>
        <button type="button" onClick={this.getFocus}>讓用戶名獲得焦點</button>
      </form>
 ) } } ReactDOM.render(<Form></Form>,document.getElementById('root'))

1.5 Refs 使用場景

  • 處理焦點、文本選擇或者媒體的控制
  • 觸發必要的動畫
  • 集成第三方 DOM 庫
補充:

函數組件執行完畢之后就被釋放了,但是會返回一個react元素,這個元素會一直存在,最后會被渲染成真實dom

 

 

 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


免責聲明!

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



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