3.Refs and the DOM

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ù)情況下它不重要。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市奸笤,隨后出現(xiàn)的幾起案子监右,更是在濱河造成了極大的恐慌,老刑警劉巖异希,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件健盒,死亡現(xiàn)場離奇詭異,居然都是意外死亡称簿,警方通過查閱死者的電腦和手機扣癣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來憨降,“玉大人父虑,你說我怎么就攤上這事∈谝” “怎么了士嚎?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長悔叽。 經(jīng)常有香客問我莱衩,道長笨蚁,這世上最難降的妖魔是什么册招? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任键痛,我火速辦了婚禮昨忆,結(jié)果婚禮上席里,老公的妹妹穿的比我還像新娘繁疤。我一直安慰自己,他們只是感情好褐啡,可當(dāng)我...
    茶點故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布褥赊。 她就那樣靜靜地躺著,像睡著了一般捶惜。 火紅的嫁衣襯著肌膚如雪鹤竭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天,我揣著相機與錄音,去河邊找鬼蜓肆。 笑死蕾额,一個胖子當(dāng)著我的面吹牛调炬,可吹牛的內(nèi)容都是我干的刀荒。 我是一名探鬼主播,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了猎拨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤蝇闭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體童谒,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡单旁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖箱熬,靈堂內(nèi)的尸體忽然破棺而出良瞧,到底是詐尸還是另有隱情尘执,我是刑警寧澤宴凉,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布誊锭,位于F島的核電站,受9級特大地震影響弥锄,放射性物質(zhì)發(fā)生泄漏丧靡。R本人自食惡果不足惜蟆沫,卻給世界環(huán)境...
    茶點故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望温治。 院中可真熱鬧饭庞,春花似錦、人聲如沸熬荆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卤恳。三九已至累盗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間突琳,已是汗流浹背若债。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留本今,地道東北人拆座。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像冠息,于是被迫代替她去往敵國和親挪凑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 深入JSX date:20170412筆記原文其實JSX是React.createElement(componen...
    gaoer1938閱讀 8,076評論 2 35
  • It's a common pattern in React to wrap a component in an ...
    jplyue閱讀 3,277評論 0 2
  • 以下內(nèi)容是我在學(xué)習(xí)和研究React時逛艰,對React的特性躏碳、重點和注意事項的提取、精練和總結(jié)散怖,可以做為React特性...
    科研者閱讀 8,244評論 2 21
  • 轉(zhuǎn)載自:前端外刊評論-知乎專欄——《深入 React 技術(shù)椪蚓欤》章節(jié)試讀 《深入 React 技術(shù)椧ё睿》盡管并不是一本...
    曉松閱讀 3,852評論 0 10
  • 黑衣,黑褲欠动,三兒走在山林里不起眼的小路上永乌。煙花三月,陽光正好具伍。 突兀的翅雏,在樹林交錯中看不真切,但那炊煙確實實實在在...
    割曉閱讀 309評論 0 1