React從入門到精通系列之(14)refs和DOM元素
https://segmentfault.com/u/zhangyatao/articles在典型的React資料流中,props是父元件與其子元件互動的唯一方式。 要修改子元件,需要使用一個新的props進行重新渲染。
但是,在某些情況下,您需要在典型資料流之外強制修改子元件。 要修改的子元件可以是React元件例項,也可以是DOM元素。 對於這兩種情況,React提供了一個以下這樣的功能。
通過ref屬性設定回撥函式
React提供可以附加到任何元件的特殊屬性。 ref
屬性接受一個回撥函式,回撥函式將在元件被掛載或解除安裝後立即執行。
當在HTML元素上使用ref
屬性時,ref
回撥函式接收一個基礎的DOM元素作為其引數。
例如,此程式碼使用ref
import React from 'react';
import ReactDOM from 'react-dom';
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// textInput是一個標準的DOM元素
this.textInput.focus();
}
render() {
return (
<div>
<input type="text" ref={input => {
this.textInput = input;
}}/>
<input type="button" value="選中上面的text input" onClick={this.focus}/>
</div>
);
}
}
ReactDOM.render(
<CustomTextInput />,
document.getElementById('root')
);
當元件裝載(mounting)時,React將使用DOM元素呼叫ref
回撥函式,並在解除安裝時用null
呼叫它。
使用ref
回撥函式是為類設定一個屬性來訪問DOM元素的常見模式。 如果您目前正在使用this.refs.myRefName
來訪問DOM引用的話,我會建議你使用此模式。
當在自定義元件上使用ref
屬性時,ref
回撥接收元件的已裝入的元件例項作為其引數。
例如,如果我們想要包裝上面的CustomTextInput
來模擬它在裝載(mounting)後立即被點選:
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focus();
}
render() {
return (
<CustomTextInput ref={input => {this.textInput = input; }} />
);
}
}
您不能在功能性元件上使用ref
屬性,因為它們沒有例項。 但是,您可以使用功能性元件的render
函式內的ref
屬性:
function CustomTextInput(props) {
// 這裡必須提前頂一個textInput,只有這樣才可以正常執行ref回撥函式
let textInput = null;
function click() {
textInput.focus();
}
return (
<div>
<input type="text" ref={input => { textInput = input; }} />
<input type="button" value="選中這個輸入框" onClick={this.click} />
</div>
);
}
不要過度使用ref
你的第一個傾向可能是使用refs
在你的應用中“make
things happen”
。
如果是這種情況,你必須花一點時間,關鍵去考慮在元件層次結構中應該擁有什麼狀態。通常,在層次結構中處於更高級別的元件“擁有”狀態是一個讓一切便清除的最適當位置。 有關示例,請參閱本系列的第10篇《提升state》。