一、The ref callback attribute
ref:reference,父組件引用子組件
組件並不是真實的 DOM節點,而是存在於內存之中的一種數據結構,叫做虛擬DOM。只有當它插入文檔以后,才會變成真實的 DOM 。根據 React 的設計,所有的 DOM 變動,都先在虛擬 DOM 上發生,然后再將實際發生變動的部分,反映在真實 DOM上,這種算法叫做DOM diff ,它可以極大提高網頁的性能表現。但是,有時需要從組件獲取真實 DOM 的節點,這時就要用到 ref 屬性.
1.1 refs.[refName]
this.refs.[refName] 返回真實的 DOM 節點。需要注意的是,由於 this.refs.[refName] 屬性獲取的是真實 DOM ,所以必須等到虛擬 DOM 插入文檔以后,才能使用這個屬性,否則會報錯。
class MyComponent extends React.Component{ handleClick(event){ this.refs.myInput.focus(); } render(){ return ( <div> <input type="text" ref="myInput" /> <button onClick={this.handleClick}>Focus on me</button> </div> ) } } React.render(<MyComponent/>,document.body)
1.2 ref為函數
ref
屬性可以是一個回調函數,而不是一個名字。這個回調函數在組件安裝后立即執行。被引用的組件作為一個參數傳遞,且回調函數可以立即使用這個組件,或保存供以后使用(或實現這兩種行為)。比如下面這段代碼,ref回調儲存DOM節點的引用。
class CustomTextInput extends React.Component { constructor(props) { super(props); this.focus = this.focus.bind(this); } focus() { // Explicitly focus the text input using the raw DOM API this.textInput.focus(); } render() { // Use the `ref` callback to store a reference to the text input DOM // element in this.textInput. return ( <div> <input type="text" ref={(input) => { this.textInput = input; }} /> <input type="button" value="Focus the text input" onClick={this.focus} /> </div> ); } }
React將在組件mounts時調用ref回調,輸入DOM元素;在組件unmount時調用ref回調,輸入null。一種常見的模式是利用ref回調來訪問DOM元素。如果你現在使用的是this.refs.myrefName來訪問ref,建議采用上面這種回調函數的形式。
當ref屬性用在一個自定義組件上,ref回調接受這個組件的mounted實例作為參數。比如,如果我們想包裹上面的CustomTextInput組件來模擬他mount后立即被單擊
class AutoFocusTextInput extends React.Component { componentDidMount() { this.textInput.focus(); } render() { return ( <CustomTextInput ref={(input) => { this.textInput = input; }} /> ); } }
你可能不會在函數組件上使用ref屬性,因為函數組件沒有實例,然而你可以在函數組件的render 函數中使用ref屬性。
function CustomTextInput(props) { // textInput must be declared here so the ref callback can refer to it let textInput = null; function handleClick() { textInput.focus(); } return ( <div> <input type="text" ref={(input) => { textInput = input; }} /> <input type="button" value="Focus the text input" onClick={handleClick} /> </div> ); }
二、不要濫用refs
當你想使用refs時,想想是否可以用state代替。最適合設置state的地方是在層級中較高的位置設置。