React.js 小書 Lesson21 – ref 和 React.js 中的 DOM 操作
轉載請註明出處,保留原文連結以及作者資訊
線上閱讀:http://huziketang.com/books/react
在 React.js 當中你基本不需要和 DOM 直接打交道。React.js 提供了一些列的 on*
方法幫助我們進行事件監聽,所以 React.js 當中不需要直接呼叫 addEventListener
的 DOM API;以前我們通過手動 DOM 操作進行頁面更新(例如藉助 jQuery),而在 React.js 當中可以直接通過 setState
的方式重新渲染元件,渲染的時候可以把新的 props
傳遞給子元件,從而達到頁面更新的效果。
React.js 這種重新渲染的機制幫助我們免除了絕大部分的 DOM 更新操作,也讓類似於 jQuery 這種以封裝 DOM 操作為主的第三方的庫從我們的開發工具鏈中刪除。
但是 React.js 並不能完全滿足所有 DOM 操作需求,有些時候我們還是需要和 DOM 打交道。比如說你想進入頁面以後自動 focus 到某個輸入框,你需要呼叫 input.focus()
的 DOM API,比如說你想動態獲取某個 DOM 元素的尺寸來做後續的動畫,等等。
React.js 當中提供了 ref
屬性來幫助我們獲取已經掛載的元素的 DOM 節點,你可以給某個 JSX 元素加上 ref
屬性:
class AutoFocusInput extends Component {
componentDidMount () {
this.input.focus()
}
render () {
return (
<input ref={(input) => this.input = input} />
)
}
}
ReactDOM.render(
<AutoFocusInput />,
document.getElementById(`root`)
)
可以看到我們給 input
元素加了一個 ref
屬性,這個屬性值是一個函式。當 input
元素在頁面上掛載完成以後,React.js 就會呼叫這個函式,並且把這個掛載以後的 DOM 節點傳給這個函式。在函式中我們把這個 DOM 元素設定為元件例項的一個屬性,這樣以後我們就可以通過 this.input
獲取到這個 DOM 元素。
然後我們就可以在 componentDidMount
中使用這個 DOM 元素,並且呼叫 this.input.focus()
的 DOM API。整體就達到了頁面載入完成就自動 focus 到輸入框的功能(大家可以注意到我們用上了 componentDidMount
這個元件生命週期)。
我們可以給任意代表 HTML 元素標籤加上 ref
從而獲取到它 DOM 元素然後呼叫 DOM API。但是記住一個原則:能不用 ref
就不用。特別是要避免用 ref
來做 React.js 本來就可以幫助你做到的頁面自動更新的操作和事件監聽。多餘的 DOM 操作其實是程式碼裡面的“噪音”,不利於我們理解和維護。
順帶一提的是,其實可以給元件標籤也加上 ref
,例如:
<Clock ref={(clock) => this.clock = clock} />
這樣你獲取到的是這個 Clock
元件在 React.js 內部初始化的例項。但這並不是什麼常用的做法,而且也並不建議這麼做,所以這裡就簡單提及,有興趣的朋友可以自己學習探索。