iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0
自我挑戰組

React 30 天學習歷程系列 第 18

# 【Day 18】 ref 使用

  • 分享至 

  • xImage
  •  

ref 是 React 中用來取得 DOM 節點的一個方法,通常是使用 ref 來處理以下這些行為:

  • 處理 focus、選擇文字等
  • 處理動畫效果
  • 與第三方套件結合
    官方文件中有提到,避免過度的使用 ref,因為用這種方式取得 DOM 元素固然方便,但使用過多可能會導致產品程式碼長期維護上的不便。另外還有一點要注意的是,在 function component 中是無法使用 ref 的,因為 function component 沒有 instance
    創建 ref 有兩種方式,分別是使用 React.createRef() 和 回調式 ref

React.createRef()

React.createRef() 是 React 中的一個方法,可以創建 ref。下面我們透過調用 React.createRef() 創建 ref 並賦給 myRef 變數,再將 myRef 放到標籤本身的 ref 屬性上,這樣就能透過 myRef 取得該標籤。

我們創建的 ref 本身是一個物件,裡面有一個屬性 { current: node },這個 current 就是我們要取得的 DOM 節點,在下面的範例中,就是 div。這個 current 當然也包含了一些 HTML 的屬性,比方範例中透過 innerHTML 取得 HTML 內的內容。

class MyComponent extends React.Component {
    // 創建 ref
    myRef = React.createRef();
    
    componentDidMount () {
        console.log(this.myRef); //訪問 ref 物件
        console.log(this.myRef.current); //訪問 DOM 節點
        console.log(this.myRef.current.innerHTML); // 訪問 DOM 的 HTML 內容
    }
    
    render () {
        return <div ref={ this.myRef }>內容</div>
    }
}

回調 ref

我們也可以透過回調函數來使用 ref。下面的範例中,我們透過在 div 上增加 ref 屬性,並利用 ref 的回調函數取得節點,這個回調函數的參數本身就是 DOM 節點。

class MyComponent extends React.Component {
    // 創建 ref
    myRef = null;
    
    componentDidMount () {
        console.log(this.myRef); //直接取得 DOM 節點
        console.log(this.myRef.innerHTML); // 訪問 DOM 的 HTML 內容
    }
    
    render () {
        // 透過 ref 回調函數來取得 DOM 節點
        return <div ref={node => this.myRef = node }>內容</div>
    }
}

ref 的運用方式

ref 有不少運用方式和時機,其中一個就是像前面提到的,利用 reffocus 的行為。下面的範例中,我們先創建一個 ref 並賦給 textInput,並放入到 input 標籤的 ref 中,這樣就能取得它的 DOM,同時我們透過 focusInput 函式去調用 textInput 執行綁定動作,這樣當點擊按鈕時,就會 focusinput

class UserProfile extends React.Component {
    constructor() {
        super ();
        this.textInput = React.createRef();
        this.focusInput = this.focusInput.bind(this);
    }

    focusInput() {
        this.textInput.current.focus();
    }

    render() {
    return (
        <div>
            <input
                type="text"
                ref={this.textInput} />
            <button onClick={this.focusInput}>click</button>
            </div>
        );
    }
}

我們也可以直接在 component 上面使用 ref,來取得 component 內的 DOM,讓元件在 mounting 完之後就自動 focus,不過這種作法一樣是只能用在 class component 上。React 是在 mounting 的階段去處理 ref,將 DOM element 賦到 refcurrent 屬性中,在 unmounting 時再去清空回 null 狀態。至於 ref 的更新是發生在 componentDidMountcomponentDidUpdate 之前。

// 在元件中使用 ref 取得 DOM element
class TextInput extends React.Component {
    constructor() {
        super();
        this.textInput = React.createRef();
        this.focusTextInput = this.focusTextInput.bind(this);
    }
    
    focusTextInput() {
        this.textInput.current.focus();
    }

    render () {
        return <div>
            <input
                type="text"
                ref={this.textInput}
            />
            <button onClick={this.focusInput}>click</button>
        </div>
    }
}
class UserProfile extends React.Component {
    constructor() {
        super();
        this.textInput = React.createRef();
    }
    
    componentDidMount() {
        this.textInput.current.focusTextInput();
    }

    render() {
    // 在 component 上使用 ref,直接去取得 component 內的 DOM 並執行 focus 行為
    return (
        <div>
            <TextInput ref={this.textInput}  />
            </div>
        );
    }
}

小結

這一篇主要是整理 ref 的基本用法,除了課程內容外,也有參考官網的說明和範例,因為官網講得更為詳細(也讓我看的頭很痛)。下一篇會透過表單事件處理,來更了解 react 中 eventref 的使用。


上一篇
【Day 17】 React event 處理方式
下一篇
【Day 19】 受控組件(Controlled Component)與非受控組件(Uncontrolled Component)
系列文
React 30 天學習歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言