鍍金池/ 教程/ HTML/ 更多的關于Refs
顯示數(shù)據(jù)
組件的引用
Controlled Input 值為 null 的情況
Reconciliation
子 props 的類型
組件的詳細說明和生命周期
傳遞 Props
特殊的非 DOM 屬性
組件 API
PureRenderMixin
雙向綁定輔助工具
瀏覽器中的工作原理
深入 JSX
表單組件
Dangerously Set innerHTML
入門
JSX 中的 If-Else
克隆組件
教程
更多的關于Refs
JSX 的 false 處理
高級性能
Mounting 后 componentWillReceiveProps 未被觸發(fā)
簡介
測試工具集
JSX 陷阱
工具集成(ToolingIntegration)
公開組件功能
通過 AJAX 加載初始數(shù)據(jù)
事件系統(tǒng)
可復用組件
this.props.children undefined
不可變數(shù)據(jù)的輔助工具(Immutability Helpers)
動態(tài)交互式用戶界面
組件的 DOM 事件監(jiān)聽
復合組件
動畫
插件
JSX 展開屬性
行內樣式
性能分析工具
類名操作
與其他類庫并行使用 React
鍵控的片段
標簽和屬性支持
組件間的通信
React (虛擬)DOM 術語
JSX 根節(jié)點的最大數(shù)量
在樣式props中快速制定像素值
頂層 API
深入理解 React
自閉合標簽
為什么使用 React?
getInitialState 里的 Props 是一個反模式
與 DOM 的差異

更多的關于Refs

從你的 render 方法中返回你的 UI 結構后,你會發(fā)現(xiàn)你想要“伸手”調用從 render 返回的組件實例的方法。通常來說,這樣做對于通過你的應用程序制作數(shù)據(jù)流是沒有必要的,因為 Reactive 數(shù)據(jù)流總是確保最新的 props 被發(fā)送到由 render() 輸出的每個孩子中。但是在一些情況下,它仍然有可能是必要或有益的。

考慮這樣一種情況,當你在把一個 <input / > 元素(存在于你的實例 sub-hierarchy 中)的值更新為一個空字符串后 ,想告訴它聚焦。

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>
      );
    }
  });

注意,在本例中,我們想要“告訴”輸入一些東西——這些東西是它不能從道具中推斷出的。在這個例子中,我們想要“告訴”它,現(xiàn)在它應該聚焦。然而,也有一些挑戰(zhàn)。從 render() 返回的不是你 “子”組件的實際組成,它僅僅是在一個特定的實例中的子組件的描述——如果你愿意的話可以是一個快照。

注意:

記住,從 render() 返回來的不是你實際繪制的子組件的實例。從 render() 返回來的僅僅是一個特定的時刻在你組成部分的 sub-hierarchy 中的子組件實例的描述。

這意味著你不應該“持有”從 render() 返回來的東西,并且指望它有任何的意義。

// 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>
    );
  }

在這個反例中,<input/ > 僅僅是 <input/ > 的描述。這個描述是用來為 <input/ > 創(chuàng)建一個真正的 支持實例。

那么, 我們怎么訪問 input的 真正的 支持實例呢?

Ref 的字符串屬性

React 支持一個非常特殊的屬性,你可以附加到任何從 render() 輸出的組件中。這個特殊的屬性允許你涉及相應的任何從 render() 返回的支持實例。它總是保證成為適當?shù)膶嵗?,在任何時候。

這個非常簡單:

  1. 給從 render 返回的東西分配 ref 屬性,如:
<input ref="myInput" />
  1. 在其他一些代碼(典型的是事件處理程序的代碼),通過 this.refs 訪問 backing instance,如:
this.refs.myInput

你可以通過調用 React.findDOMNode(this.refs.myInput) 直接訪問組件的 DOM 節(jié)點。

ref 回調屬性

ref 屬性可以是一個回調函數(shù),而不是一個名字。這個回調函數(shù)在組件安裝后立即執(zhí)行。被引用的組件作為一個參數(shù)傳遞,且回調函數(shù)可以立即使用這個組件,或保存供以后使用(或實現(xiàn)這兩種行為)。

它與把 ref 屬性分配給從 render 返回來的東西一樣簡單,如:

<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>
      );
    }
  });

在這個例子中,render 函數(shù)返回 <input/ > 實例的描述。但真正的實例是通過 this.refs.theInput 訪問的。只要帶有 ref =“theInput” 的子組件從 render 返回,this.refs.theInput 就會訪問適當?shù)膶嵗_@甚至能在更高的級別(non-DOM)組件中實現(xiàn),如 <Typeahead ref = " myTypeahead " / >。

總結

向一個特定的子實例發(fā)送消息,Refs 是一個很好的方式,而通過流動式接收 Reactive 的 propsstate 的方式可能是不方便的。然而,對于你的應用程序中的流動數(shù)據(jù)來說,refs 應該不是你的首選抽象特性。默認情況下,為用例使用 Reactive 數(shù)據(jù)流并保存 refs 本來就是無功無過的。

好處:

  • 你可以在組件類中定義任何公共方法(如在 Typeahead 中的復位方法),并通過 refs(如 this.refs.myTypeahead.reset())調用這些公共方法。
  • 執(zhí)行 DOM 測量幾乎總是需要接觸“本地”組件,如 <input/ >,并通過 React.findDOMNode(this.refs.myInput) 訪問它的底層 DOM 節(jié)點。Refs 是可行的可靠的方法之一。
  • refs 自動為你 book-kept!如果子組件被摧毀,那么它的 ref 也被摧毀了。在這里不必擔心內存(除非你為保留自己的 reference 做了一些瘋狂的事)。

注意事項:

  • 永遠不要訪問組件的 render 方法內部的 refs——或任何組件的 render 方法正在 call satck 中運行時,也不要訪問 refs。
  • 如果你想保存 Google Closure Compiler Crushing 的彈性,確保永遠不要訪問作為字符串被指定的屬性。這意味著如果你的 ref 被定義為 ref =“myRefString”,你必須使用 this.refs['myRefString'] 來訪問。
  • 如果你還沒有用 React 給幾個應用程序編程,那么你通常首先會傾向于嘗試使用 refs 來“讓事情發(fā)生”在你的應用程序中。如果是這樣的話,花點時間,更為慎重的思考一下 state 應該屬于組件層次結構的什么位置。通常情況下,你會清楚地發(fā)現(xiàn),“擁有”那個 state 的適當?shù)奈恢檬歉叩膶哟谓Y構中。把 state 放置在那里通??梢韵魏蜗胍褂?ref 來“讓事情發(fā)生”的現(xiàn)象——相反,數(shù)據(jù)流通常會實現(xiàn)你的目標。
上一篇:為什么使用 React?下一篇:類名操作