在典型的React數據流中,props是父組件與其子組件交互的惟一方式。要修改子項,請使用new props 從新呈現它。可是,在某些狀況下,須要在典型數據流以外強制修改子項。要修改的子項能夠是React組件的實例,也能夠是DOM元素。對於這兩種狀況,React都提供了api。node
refs有一些很好的用例:api
避免將refs用於能夠聲明性地完成的任何操做。數組
*不要過分使用Refs函數
若是您以前使用過React,那麼您可能熟悉一箇舊的API,其中ref屬性是一個字符串"textInput",而且DOM節點被訪問爲this.refs.textInput。建議不要使用它,由於字符串引用有一些問題,被認爲是遺留問題,極可能會在將來的某個版本中刪除。動畫
當組件安裝時,React將使用DOM元素調用ref回調,並在卸載時調用null。
在componentDidMount或componentDidUpdate觸發以前,Refs保證是最新的.this
class CustomTextInput extends React.Component { constructor(props) { super(props); this.textInput = null; this.setTextInputRef = element => { this.textInput = element; }; this.focusTextInput = () => { // Focus the text input using the raw DOM API if (this.textInput) this.textInput.focus(); }; } componentDidMount() { // autofocus the input on mount this.focusTextInput(); } render() { // Use the `ref` callback to store a reference to the text input DOM // element in an instance field (for example, this.textInput). return ( <div> <input type="text" ref={this.setTextInputRef} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } }
class Example extends React.Component { handleClick() { // 使用原生的 DOM API 獲取焦點 this.refs.myInput.focus (); } render() { // 當組件插入到 DOM 後,ref 屬性添加一個組件的引用於到 this.refs return ( <div> <input type="text" ref="myInput" /> <input type="button" value="點我輸入框獲取焦點" onClick={this.handleClick.bind(this)} /> </div> ); } }
React.createRef()React 16.3中引入的API。若是您使用的是早期版本的React,咱們建議您使用回調引用。code
Refs是使用屬性建立的,React.createRef()並經過ref屬性附加到React元素。在構造組件時,一般將Refs分配給實例屬性,以即可以在整個組件中引用它們。component
class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } render() { return <div ref={this.myRef} />; } }
當ref被傳遞給元素時render,對該節點的引用變得能夠在currentref 的屬性處訪問對象
const node = this.myRef.current;
ref的值根據節點的類型而有所不一樣生命週期
您可能沒法ref在函數組件上使用該屬性,由於它們沒有實例。
class CustomTextInput extends React.Component { constructor(props) { super(props); // create a ref to store the textInput DOM element this.textInput = React.createRef(); this.focusTextInput = this.focusTextInput.bind(this); } focusTextInput() { // Explicitly focus the text input using the raw DOM API // Note: we're accessing "current" to get the DOM node this.textInput.current.focus(); } render() { // tell React that we want to associate the <input> ref // with the `textInput` that we created in the constructor return ( <div> <input type="text" ref={this.textInput} /> <input type="button" value="Focus the text input" onClick={this.focusTextInput} /> </div> ); } }
current當組件安裝時,React將爲該屬性分配DOM元素,並null在卸載時將其分配回。ref更新發生以前componentDidMount或componentDidUpdate生命週期方法。
function MyFunctionComponent() { return <input />; } class Parent extends React.Component { constructor(props) { super(props); this.textInput = React.createRef(); } render() { // This will *not* work! return ( <MyFunctionComponent ref={this.textInput} /> ); } }
**若是須要引用它,則應該將組件轉換爲類,就像您須要生命週期方法或狀態時同樣。
可是,只要引用DOM元素或類組件,就能夠在函數組件中使用該ref屬性:**
function CustomTextInput(props) { // textInput must be declared here so the ref can refer to it let textInput = React.createRef(); function handleClick() { textInput.current.focus(); } return ( <div> <input type="text" ref={textInput} /> <input type="button" value="Focus the text input" onClick={handleClick} /> </div> ); }
在極少數狀況下,可能但願從父組件訪問子節點的DOM節點。一般不建議這樣作,由於它會破壞組件封裝,但它偶爾可用於觸發焦點或測量子DOM節點的大小或位置。
雖然能夠向子組件添加引用,但這不是一個理想的解決方案,由於只能得到組件實例而不是DOM節點。此外,這不適用於功能組件。
若是使用React 16.3或更高版本,咱們建議在這些狀況下使用ref forwarding。引用轉發容許組件選擇將任何子組件的引用公開爲本身的組件。能夠在ref轉發文檔中找到有關如何將子DOM節點公開給父組件的詳細示例。
若是您使用React 16.2或更低版本,或者您須要比ref轉發提供的更多靈活性,您可使用此替代方法並明確地將ref做爲不一樣名稱的prop傳遞。
若是可能,建議不要暴露DOM節點,但它能夠是一個有用的逃生艙。請注意,此方法要求向子組件添加一些代碼。若是您徹底沒法控制子組件實現,則最後一個選項是使用findDOMNode(),但不鼓勵使用它StrictMode。