首頁 >web前端 >js教程 >react中的ref是什麼

react中的ref是什麼

藏色散人
藏色散人原創
2021-02-01 09:13:195995瀏覽

ref是React提供的用來操縱React元件實例或DOM元素的介面;回呼函數就是在dom節點或元件上掛載函數,函數的入參是dom節點或元件實例,達到的效果與字串形式是一樣的,都是獲取其引用。

react中的ref是什麼

在react典型的資料流中,props傳遞是父子元件互動的唯一方式;透過傳遞一個新的props值來使子元件重新re-render,從而達到父子元件通訊。當然,就像react官網所描述的一樣,在react典型的資料量之外,某些情況下(例如和第三方的dom庫整合,或者某個dom元素focus等)為了修改子組件我們可能需要另一種方式,這就是ref方式。

ref 簡介

React提供的這個ref屬性,表示為對元件真正實例的引用,其實就是ReactDOM.render()返回的元件實例;需要區分一下,ReactDOM.render()渲染元件時傳回的是元件實例;而渲染dom元素時,回傳是特定的dom節點。

例如,下面程式碼:

    const domCom = <button>button</button>;
    const refDom = ReactDOM.render(domCom,container);
    //ConfirmPass的组件内容省略
    const refCom = ReactDOM.render(<confirmpass></confirmpass>,container);
    console.log(refDom);
    console.log(refCom);

上述程式碼回傳控制台結果如下圖所示:

react中的ref是什麼

ref可以掛到任何元件上,可以掛到元件上也可以是dom元素上;二者不同是與上圖答案一樣:

##掛到元件(這裡元件指的是有狀態元件)上的ref表示對元件實例的引用,而掛載到dom元素上時表示具體的dom元素節點。

ref可以設定回呼函數

ref屬性可以設定為一個回呼函數,這也是官方強烈推薦的用法;這個函數執行的時機是:

  • 元件被掛載後,回呼函數立即執行,回呼函數的參數為該元件的特定實例。

  • 元件被卸載或原有的ref屬性本身改變時,回呼也會立即執行,此時回呼函數參數為null,以確保記憶體外洩。

相關推薦:《

react教學

#例如下面程式碼:

    RegisterStepTwo = React.createClass({
        getInitialState(){
          return {visible: true};
        },
      changeVisible(){
        this.setState({visible: !this.state.visible});
      },
      refCb(instance){
        console.log(instance);
      },
      render(){
        return(
          <p>
            <button>{this.state.visible ? '卸载' : '挂载'}ConfirmPass
            </button>
            {
              this.state.visible ?
                <confirmpass></confirmpass>: null
             }
           </p>
         )
      }
    });
上述程式碼,渲染到頁面時可以發現console.log出對應的元件實例,切換按鈕時,

ConfirmPass也在掛載與卸載之間切換,所以能看到不同的console.log結果。

ref可以設定字串

ref也可以設定為字串值,而不是回呼函數;這種方式基本上不建議使用,或者在未來的react版本中不會再支持該方式,但是可以了解一下。

例如下面

input設定ref的值為字串。

<input>
然後在其他地方如事件回呼中透過

this.refs.input可以存取到該元件實例,其實就是dom元素節點。

let inputEl = this.refs.input;
//然后通过inputEl来完成后续的逻辑,如focus、获取其值等等
取得ref參考元件對應的dom節點

不管ref設定值是回呼函數還是字串,都可以透過

ReactDOM.findDOMNode(ref)來取得元件掛載後真正的dom節點。

但是對於html元素使用ref的情況,ref本身引用的就是該元素的實際dom節點,無需使用

ReactDOM.findDOMNode(ref)來獲取,該方法常用於React組件上的ref。

ref在有狀態元件中的使用

上文說到過

ref用到react有狀態元件時,ref引用的是元件的實例;所以可以透過子元件的ref可以存取到子元件實例的propsstaterefs、實例方法(非繼承而來的方法)等等。

使用ref存取子元件情況可能是以下case:

  • 存取子元件的某個特定的dom節點完成某些邏輯,並透過

    this. refs.childComponentRefName.refs.someDomRefName來完成,例如segmentfault上提問者提出的問題。

  • 可以存取子元件的公共實例方法完成某寫邏輯。例如子元件定義了一個

    reset方法用來重設子元件表單元素值,這時父元件可以透過this.refs.childComponentRefName.reset()來完成子元件表單元素的重置。

  • ...

不過話說回來,react不建議在父元件中直接存取子元件的實例方法來完成某些邏輯,在大部分情況下請使用標準的react資料流的方式來代替則更為清晰;

另外,上述case在組件關係嵌套很深時,這種方式就顯得極為醜陋。

ref在无状态组件中的使用

上文说到的react组件都是指有状态的,对于无状态组件stateless component而言,正如这篇文章React创建组件的三种方式及其区别里描述的一样,无状态组件是不会被实例化的,在父组件中通过ref来获取无状态子组件时,其值为null,所以:

无法通过ref来获取无状态组件实例。

虽然无法通过ref获取无状态组件实例,但是可以结合复合组件来包装无状态组件来在其上使用ref引用。

另外,对于无状态组件我们想访问的无非是其中包含的组件或者dom元素,我们可以通过一个变量来保存我们想要的组件或者dom元素组件的实例引用。例如下面代码:

function TestComp(props){
    let refDom;
    return (<p>
        </p><p> refDom = node}>
            ...
        </p>
    )
}

这样,可以通过变量refDom来访问到无状态组件中的指定dom元素了,访问其中的其他组件实例类似。

ref在HOC中存在问题

react的HOC是高阶组件,简单理解就是包装了一个低阶的组件,最后返回一个高阶的组件;高阶组件其实是在低阶组件基础上做了一些事情,比方说antd组件的Form create的方法,它就是在为低阶组件封装了一些特殊的属性,比如form属性。

既然HOC会基于低阶组件生成一个新的高阶组件,若用ref就不能访问到我们真正需要的低阶组件实例,我们访问到的其实是高阶组件实例。所以:

若HOC不做特殊处理,ref是无法访问到低阶组件实例的

要想用ref访问低阶组件实例,就必须得HOC支持,就像Redux的connect方法提供的withRef属性来访问低阶组件一样。具体可以参考这里。

总结

ref提供了一种对于react标准的数据流不太适用的情况下组件间交互的方式,例如管理dom元素focus、text selection以及与第三方的dom库整合等等。 但是在大多数情况下应该使用react响应数据流那种方式,不要过度使用ref。

另外,在使用ref时,不用担心会导致内存泄露的问题,react会自动帮你管理好,在组件卸载时ref值也会被销毁。

最后补充一点:

不要在组件的render方法中访问ref引用,render方法只是返回一个虚拟dom,这时组件不一定挂载到dom中或者render返回的虚拟dom不一定会更新到dom中。

以上是react中的ref是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn