React版本:15.4.2
**翻譯:xiyoki **
在典型的React數(shù)據(jù)流中誊涯,props是父組件與其children交互的唯一方式胞谈。要修改child歉铝,你需使用新的props重新渲染父組件。但是谍婉,在一些情況下稚疹,你需要在典型的數(shù)據(jù)流之外強制修改child内狗。要修改的child可以是React組件的實例其屏,也可以是DOM元素。對于這兩種情況偎行,React提供了一個 escape hatch(安全艙口; 逃口)蛤袒。
When to Use Refs
幾個好的refs使用案例:
- 管理焦點膨更、文本選擇框或媒體重放。
- 觸發(fā)命令式動畫珍德。
- 與第三方DOM庫集成。
避免在可聲明的事物上使用refs薄料。
例如摄职,不在Dialog
組件上暴露open()
和close()
方法,而是向它傳遞isOpen
屬性谷市。
Adding a Ref to a DOM Element
React支持你附加一個特殊的屬性到任何組件迫悠。該ref
屬性接收一個回調(diào)函數(shù)作為參數(shù)及皂,在組件被mounted或unmounted后且改,該回調(diào)就被立即執(zhí)行又跛。
當(dāng)在HTML元素上使用ref
屬性時慨蓝,ref
回調(diào)接收基礎(chǔ)DOM元素作為參數(shù)端幼。例如,此代碼使用ref
回調(diào)來儲存對DOM節(jié)點的引用:
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 an instance field (for example, this.textInput).
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
當(dāng)組件mounts時此熬,React會調(diào)用ref
回調(diào)犀忱,并向其傳入DOM元素扶关。當(dāng)組件unmounts時节槐,React會調(diào)用ref
回調(diào),并向其傳入null哥倔。
使用ref
回調(diào)為類設(shè)置一個屬性未斑,是訪問DOM元素的常見模式。首選方法是在ref
回調(diào)中設(shè)置屬性府阀,就像上面的例子芽突。甚至有一個簡便的書寫方式:ref={input => this.textInput = input}
寞蚌。
Adding a Ref to a Class Component
當(dāng)ref
屬性被用在自定義類組件上時,ref
回調(diào)接收已mounted的組件實例作為參數(shù)壹哺。例如管宵,如果我們想在CustomTextInput
上包裹一圈攀甚,模擬組件mounting后,它直接被點擊:
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focus();
}
render() {
return (
<CustomTextInput
ref={(input) => { this.textInput = input; }} />
);
}
}
注意炸庞,只有CustomTextInput
被聲明為類時才有效:
class CustomTextInput extends React.Component {
// ...
}
Refs and Functional Components
你不能(在引用功能組件時)在功能組件上使用ref
屬性荚斯,因為功能組件沒有實例:
function MyFunctionalComponent() {
return <input />;
}
class Parent extends React.Component {
render() {
// This will *not* work!
return (
<MyFunctionalComponent
ref={(input) => { this.textInput = input; }} />
);
}
}
如果你需要一個ref鲸拥,你應(yīng)該將組件轉(zhuǎn)換為一個類刑赶,就像你需要聲明周期方法或狀態(tài)時一樣。
但你可以在功能組件內(nèi)部使用ref
屬性金踪,只要是涉及DOM元素或類組件:
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>
);
}
Don't Overuse Refs(不要過度使用Refs)
你使用refs的第一個傾向可能是讓事情在你的應(yīng)用程序中發(fā)生胡岔。如果是這種情況靶瘸,請花一點時間,著重考慮狀態(tài)應(yīng)該在組件層次結(jié)構(gòu)的什么位置屋剑。通常唉匾,擁有該狀態(tài)的適當(dāng)位置在組件層次結(jié)構(gòu)中的層級更高匠楚。
Legacy API: String Refs(舊版API:字符串Refs)
如果你之前使用過React,你可能會熟悉一個較舊的API,其中ref
屬性是一個字符串峡懈,如像"textInput"
,DOM節(jié)點被這樣訪問this.refs.textInput
逮诲。我們建議不這樣使用。因為字符串引用有一些被認(rèn)為是遺留的問題裆甩,并且可能在未來的一個版本中被刪除。如果你目前正在使用this.refs.textInput
訪問refs,我們建議你使用回調(diào)模式冻河。
Caveats(注意)
如果ref
回調(diào)被定義為內(nèi)聯(lián)函數(shù)叨叙,它將在更新期間被調(diào)用兩次擂错,第一次調(diào)用傳入null,第二次調(diào)用傳入DOM 元素樱蛤。這是因為函數(shù)的新實例是通過每次渲染創(chuàng)建的钮呀,因此React需要清除舊的引用并設(shè)置新的引用爽醋。你可以通過將ref
回調(diào)定義為類上的綁定方法來避免這種情況蚂四,但請注意遂赠,在大多數(shù)情況下它不重要。