從你的 render 方法中返回你的 UI 結(jié)構(gòu)后,你會(huì)發(fā)現(xiàn)你想要“伸手”調(diào)用從 render 返回的組件實(shí)例的方法。通常來(lái)說(shuō),這樣做對(duì)于通過(guò)你的應(yīng)用程序制作數(shù)據(jù)流是沒(méi)有必要的,因?yàn)?Reactive 數(shù)據(jù)流總是確保最新的 props
被發(fā)送到由 render()
輸出的每個(gè)孩子中。但是在一些情況下,它仍然有可能是必要或有益的。
考慮這樣一種情況,當(dāng)你在把一個(gè) <input / >
元素(存在于你的實(shí)例 sub-hierarchy 中)的值更新為一個(gè)空字符串后
,想告訴它聚焦。
var App = React.createClass({ getInitialState: function() { return {userInput: ''}; }, handleChange: function(e) { this.setState({userInput: e.target.value}); }, clearAndFocusInput: function() { this.setState({userInput: ''}); // Clear the input // We wish to focus the <input /> now! }, render: function() { return ( <div> <div onClick={this.clearAndFocusInput}> Click to Focus and Reset </div> <input value={this.state.userInput} onChange={this.handleChange} /> </div> ); } });
注意,在本例中,我們想要“告訴”輸入一些東西——這些東西是它不能從道具中推斷出的。在這個(gè)例子中,我們想要“告訴”它,現(xiàn)在它應(yīng)該聚焦。然而,也有一些挑戰(zhàn)。從 render()
返回的不是你 “子”組件的實(shí)際組成,它僅僅是在一個(gè)特定的實(shí)例中的子組件的描述——如果你愿意的話可以是一個(gè)快照。
注意:
記住,從
render()
返回來(lái)的不是你實(shí)際繪制的子組件的實(shí)例。從render()
返回來(lái)的僅僅是一個(gè)特定的時(shí)刻在你組成部分的 sub-hierarchy 中的子組件實(shí)例的描述。
這意味著你不應(yīng)該“持有”從 render()
返回來(lái)的東西,并且指望它有任何的意義。
// counterexample: DO NOT DO THIS! render: function() { var myInput = <input />; // I'm going to try to call methods on this this.rememberThisInput = myInput; // input at some point in the future! YAY! return ( <div> <div>...</div> {myInput} </div> ); }
在這個(gè)反例中,<input/ >
僅僅是 <input/ >
的描述。這個(gè)描述是用來(lái)為 <input/ >
創(chuàng)建一個(gè)真正的 支持實(shí)例。
那么, 我們?cè)趺丛L問(wèn) input的 真正的 支持實(shí)例呢?
React 支持一個(gè)非常特殊的屬性,你可以附加到任何從 render()
輸出的組件中。這個(gè)特殊的屬性允許你涉及相應(yīng)的任何從 render()
返回的支持實(shí)例。它總是保證成為適當(dāng)?shù)膶?shí)例,在任何時(shí)候。
這個(gè)非常簡(jiǎn)單:
給從 render
返回的東西分配 ref
屬性,如:
<input ref="myInput" />
在其他一些代碼(典型的是事件處理程序的代碼),通過(guò) this.refs
訪問(wèn) backing instance,如:
this.refs.myInput
你可以通過(guò)調(diào)用 React.findDOMNode(this.refs.myInput)
直接訪問(wèn)組件的 DOM 節(jié)點(diǎn)。
ref
屬性可以是一個(gè)回調(diào)函數(shù),而不是一個(gè)名字。這個(gè)回調(diào)函數(shù)在組件安裝后立即執(zhí)行。被引用的組件作為一個(gè)參數(shù)傳遞,且回調(diào)函數(shù)可以立即使用這個(gè)組件,或保存供以后使用(或?qū)崿F(xiàn)這兩種行為)。
它與把 ref
屬性分配給從 render
返回來(lái)的東西一樣簡(jiǎn)單,如:
<input ref={ function(component){ React.findDOMNode(component).focus();} } />
var App = React.createClass({ getInitialState: function() { return {userInput: ''}; }, handleChange: function(e) { this.setState({userInput: e.target.value}); }, clearAndFocusInput: function() { // Clear the input this.setState({userInput: ''}, function() { // This code executes after the component is re-rendered React.findDOMNode(this.refs.theInput).focus(); // Boom! Focused! }); }, render: function() { return ( <div> <div onClick={this.clearAndFocusInput}> Click to Focus and Reset </div> <input ref="theInput" value={this.state.userInput} onChange={this.handleChange} /> </div> ); } });
在這個(gè)例子中,render 函數(shù)返回 <input/ >
實(shí)例的描述。但真正的實(shí)例是通過(guò) this.refs.theInput
訪問(wèn)的。只要帶有 ref =“theInput”
的子組件從 render 返回,this.refs.theInput
就會(huì)訪問(wèn)適當(dāng)?shù)膶?shí)例。這甚至能在更高的級(jí)別(non-DOM)組件中實(shí)現(xiàn),如 <Typeahead ref = " myTypeahead " / >
。
向一個(gè)特定的子實(shí)例發(fā)送消息,Refs 是一個(gè)很好的方式,而通過(guò)流動(dòng)式接收 Reactive 的 props
和 state
的方式可能是不方便的。然而,對(duì)于你的應(yīng)用程序中的流動(dòng)數(shù)據(jù)來(lái)說(shuō),refs 應(yīng)該不是你的首選抽象特性。默認(rèn)情況下,為用例使用 Reactive 數(shù)據(jù)流并保存 ref
s 本來(lái)就是無(wú)功無(wú)過(guò)的。
你可以在組件類中定義任何公共方法(如在 Typeahead 中的復(fù)位方法),并通過(guò) refs(如 this.refs.myTypeahead.reset()
)調(diào)用這些公共方法。
執(zhí)行 DOM 測(cè)量幾乎總是需要接觸“本地”組件,如 <input/ >
,并通過(guò) React.findDOMNode(this.refs.myInput)
訪問(wèn)它的底層 DOM 節(jié)點(diǎn)。Refs 是可行的可靠的方法之一。
refs 自動(dòng)為你 book-kept!如果子組件被摧毀,那么它的 ref 也被摧毀了。在這里不必?fù)?dān)心內(nèi)存(除非你為保留自己的 reference 做了一些瘋狂的事)。
永遠(yuǎn)不要訪問(wèn)組件的 render 方法內(nèi)部的 refs——或任何組件的 render 方法正在 call satck 中運(yùn)行時(shí),也不要訪問(wèn) refs。
如果你想保存 Google Closure Compiler Crushing 的彈性,確保永遠(yuǎn)不要訪問(wèn)作為字符串被指定的屬性。這意味著如果你的 ref 被定義為 ref =“myRefString”
,你必須使用 this.refs['myRefString']
來(lái)訪問(wèn)。
如果你還沒(méi)有用 React 給幾個(gè)應(yīng)用程序編程,那么你通常首先會(huì)傾向于嘗試使用 refs 來(lái)“讓事情發(fā)生”在你的應(yīng)用程序中。如果是這樣的話,花點(diǎn)時(shí)間,更為慎重的思考一下 state
應(yīng)該屬于組件層次結(jié)構(gòu)的什么位置。通常情況下,你會(huì)清楚地發(fā)現(xiàn),“擁有”那個(gè) state 的適當(dāng)?shù)奈恢檬歉叩膶哟谓Y(jié)構(gòu)中。把 state 放置在那里通??梢韵魏蜗胍褂?span id="5w88nvj" class="Apple-converted-space"> ref
來(lái)“讓事情發(fā)生”的現(xiàn)象——相反,數(shù)據(jù)流通常會(huì)實(shí)現(xiàn)你的目標(biāo)。
更多建議: