<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] `React`中的`Refs`提供了一種訪問`render()`方法中創建的`React`元素(或`DOM`節點)的方法。 當父組件需要與子組件交互時,我們通常使用 [props](https://reactjs.org/docs/components-and-props.html) 來傳遞相關信息。 但是,**在某些情況下,我們可能需要修改子項,而不用新的`props`重新呈現 (re-rendering) 它**。這時候就需要`refs`出場了。 # 什么時候使用 Refs ? 我們建議在以下情況下使用 `refs`: * 與第三方 `DOM` 庫集成 * 觸發命令式動畫 * 管理焦點,文本選擇或媒體播放 > 譯注:第三點是否也可以理解為使用 `event` 對象呢?在 React 中就是合成事件 (SyntheticEvent)。 > **官方文檔中提到:避免使用 `refs` 來做任何可以通過聲明式實現來完成的事情**。 所以一旦我們確定我們需要使用 `refs`,我們如何使用它們呢? # 在 React 中使用 Refs 您可以通過多種方式使用`refs`: * [React.createRef()](https://reactjs.org/docs/refs-and-the-dom.html) * 回調引用 (Callback refs) * String refs(已過時,這 API 將被棄用) * 轉發`refs`(Forwarding refs) ## `React.createRef()` 使用`React.createRef()`創建引用,并通過`ref`屬性附加到React元素上。 在構造組件時,通常將 Refs 分配給實例屬性,以便在整個組件中引用它們。 ``` // Ref.js 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> ); } } ``` 在上面的代碼塊中,我們構建了一個按鈕,當單擊它時,**該頁面會自動聚焦在輸入框上。** 首先,我們在構造方法中**創建一個 React `ref` 實例**,并將其賦值給 `this.textInput`,然后通過`ref` 屬性將其分配給 `input`元素。 ``` <input?type="text"?ref={this.textInput} /> ``` 注意,當 `ref` 屬性被一個`HTML` 元素使用時(比如當前示例中的 `input`元素),在 `constructor` 中使用 `React.createRef()` 創建的 `ref`會接收 **來自底層`DOM`元素的 `current`值**。 > 譯注:這里的 `current` 應該是[合成事件(SyntheticEvent)](http://react.html.cn/docs/events.html) 這意味著訪問 `DOM` 值,我們需要寫這樣的東西: ``` this.textInput.current; ``` ## Refs 回調 **Refs 回調** 是在 React 中使用 `ref` 的另一種方式。要以這種方式使用 ref,我們需要為 ref 屬性設置回調函數。 當我們設置 ref 時,React 會調用這個函數,并將 element 作為第一個參數傳遞給它。 ``` // Refs.js class CustomTextInput extends React.Component { constructor(props) { super(props); this.textInput = null; // 回調,傳入的 this.setTextInputRef = element => { this.textInput = element; }; } handleSubmit = e => { e.preventDefault(); console.log(this.textInput.value); }; render() { return ( <div> <form onSubmit={e => this.handleSubmit(e)}> <input type="text" ref={this.setTextInputRef} /> <button>Submit</button> </form> </div> ); } ``` 上面的示例中,我們將 input 標簽的 `ref` 設置為 `this.setTextInputRef`。 * 當組件安裝時,React 會將 DOM 元素傳遞給 ref 的回調; * 當組件卸載時,則會傳遞 `null`。 (`ref` 回調會在 `componentDidMount` 和 `componentDidUpdate` 生命周期之前調用。) ## `React.forwardRef` 不能在函數組件上使用`ref`屬性,因為函數組件沒有實例。 如果您希望引用函數組件,您可以使用`forwardRef`可能與`useImperativeHandle`結合使用),或者您可以將它轉換為類組件。 ``` // Ref.js // 普通的函數組件 是不會有 ref 參數的,React.forwardRef 返回一個組件 const TextInput = React.forwardRef((props, ref) => ( <input type="text" placeholder="Hello World" ref={ref} /> )); const inputRef = React.createRef(); class CustomTextInput extends React.Component { handleSubmit = e => { e.preventDefault(); console.log(inputRef.current.value); }; render() { return ( <div> <form onSubmit={e => this.handleSubmit(e)}> <TextInput ref={inputRef} /> <button>Submit</button> </form> </div> ); } } ``` `Ref forwarding`允許組件接收一個`ref`,并將它向下傳遞(換句話說,“轉發”它)給子組件。 在上面的示例中,我們使用`input`標簽創建了一個名為`TextInput`的組件。那么,我們如何將`ref`傳遞或轉發到`input`標簽呢? 首先,我們使用下面的代碼創建一個`ref`: ``` const?inputRef = React.createRef(); ``` 然后,我們**通過組件 `<TextInput ref={inputRef}>` 的 `ref` 屬性的值,將 `ref` 向下傳遞**。然后`React` 將會把 `ref` 作為第二個參數轉發給 `forwardRef` 函數(這個是在 React 框架層面完成的事情)。 接下來,我們將此 `ref` 參數轉發給`<input ref={ref}>`。現在可以在外層組件通過 `inputRef.current` 訪問 DOM 節點的值了。 ## 高階組件的 ref 如果我要操作一個高階組件 的 DOM ,怎么辦? ref 是不能像 props 一樣,往下面傳遞的,因此想要往下面傳遞,必須要用到`React.forwardRef`這個 API。 ``` // by 司徒正美 const ThemeContext = React.createContext('light'); class ThemeProvider extends React.Component { state = {theme: 'light'}; render() { return ( <ThemeContext.Provider value={this.state.theme}> {this.props.children} </ThemeContext.Provider> ); } } class FancyButton extends React.Component { buttonRef = React.createRef(); focus() { this.buttonRef.current.focus(); } render() { const {label, theme, ...rest} = this.props; return ( <button {...rest} className={`${theme}-button`} ref={this.buttonRef}> {label} </button> ); } } function withTheme(Component) { // React.forwardRef 會提供 第二個參數"ref",然后就可以直接把其附加到組件上 function ThemedComponent(props, ref) { return ( <ThemeContext.Consumer> {theme => ( <Component {...props} ref={ref} theme={theme} /> )} </ThemeContext.Consumer> ); } // These next lines are not necessary, // But they do give the component a better display name in DevTools, // e.g. "ForwardRef(withTheme(MyComponent))" const name = Component.displayName || Component.name; ThemedComponent.displayName = `withTheme(${name})`; // 告訴 React 傳遞 "ref" 到 ThemedComponent. return React.forwardRef(ThemedComponent); } const fancyButtonRef = React.createRef(); const FancyThemedButton = withTheme(FancyButton); // fancyButtonRef 現在指向 FancyButton <FancyThemedButton label="Click me!" onClick={handleClick} ref={fancyButtonRef} />; ``` # 結論 與通過`props`和`state`不同,`Refs`是一種將數據傳遞給特定子實例的好方法。 你必須要小心,因為`refs`操縱實際的`DOM`,而不是虛擬的`DOM`,這與`React`思維方式相矛盾。因此,雖然`refs`不應該是通過應用程序流動數據的默認方法,但是當您需要時,它們是可以從`DOM`元素讀取數據的好方法。 # 參考 推薦下「司徒正美」大佬的[React v16.3.0: New lifecycles and context API](https://segmentfault.com/a/1190000014083970),createRef API,forwardRef API 中的示例可以作為補充閱讀。 [https://segmentfault.com/a/1190000019277029](https://segmentfault.com/a/1190000019277029)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看