ReactJS - Refs 和 DOM
您好,未來的 React 開發者!今天,我們將深入一個令人興奮的主題,這將幫助您在 React 應用程序中直接與 DOM 元素交互。請坐好,因為我們即將探索 Refs 和 DOM 的世界!
Refs 是什麼?
在我們深入細節之前,讓我們先了解 Refs 是什麼。在 React 中,"Ref" 是 "reference" 的縮寫。它就像給一個特定的元素貼上名標籤,這樣您可以稍後輕鬆找到它。想像您在一個大派對上,您想跟踪您最好的朋友。您可能會給他們一頂特殊的帽子或獨特的名標籤。這基本上就是 React 中 Ref 的作用 - 它幫助您跟踪特定的元素。
我們為什麼需要 Refs?
您可能會想,"我們為什麼不能直接使用常规的 JavaScript 選擇元素?" 在 React 中,我們試圖避免直接操作 DOM(文件對象模型),因為 React 有其自己的高效更新 UI 的方式。然而,有時候我們需要脫離 React 的聲明性範式,直接與 DOM 元素工作。這就是 Refs 派上用場的地方!
使用 createRef() 創建 Refs
讓我們從看我們如何在 React 中創建一個 Ref 開始。我們使用一個名為 createRef()
的方法。
createRef 方法的簽名
createRef()
的簽名非常簡單:
React.createRef()
就這樣!沒有參數,沒有複雜性。它返回一個具有單一屬性的普通對象:current
。最初,這個 current
屬性被設置為 null
。
讓我們看一個例子:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
在這個例子中,我們在構造函數中創建一個 Ref,並將其分配給 this.myRef
。然後在 render
方法中,我們使用 ref
屬性將這個 Ref 附加到一個 div
元素。
應用 Ref
現在我們已經創建了我們的 Ref,讓我們看看我們如何使用它。有幾種方法可以應用 Ref:
1. 在 DOM 元素上使用 Refs
最常見的使用案例是將 Ref 应用到 DOM 元素:
class AutoFocusInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.inputRef.current.focus();
}
render() {
return <input ref={this.inputRef} />;
}
}
在這個例子中,我們為輸入元素創建了一個 Ref。在組件挂载後,我們使用 Ref 自動聚焦到輸入框。Ref 的 current
屬性給我們提供了實際的 DOM 节點的訪問權。
2. 在類組件上使用 Refs
您也可以在類組件上使用 Refs:
class AutoScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}
componentDidUpdate() {
const node = this.listRef.current;
node.scrollToItem(0);
}
render() {
return <MyListComponent ref={this.listRef} />;
}
}
在這種情況下,this.listRef.current
將指向 MyListComponent
類的實例。
3. 在函數組件上使用 Refs
函數組件不能直接被賦予 Refs,但您可以使用 forwardRef
函數來傳遞 Refs:
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.buttonRef = React.createRef();
}
render() {
return <FancyButton ref={this.buttonRef}>點我!</FancyButton>;
}
}
在這個例子中,FancyButton
使用 forwardRef
將 Ref 透傳到實際的按鈕元素。
createRef 的使用案例
現在我們知道如何創建和應用 Refs,讓我們看看一些常見的使用案例:
1. 管理焦點、文本選擇或媒體播放
class TextInput extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
focusTextInput = () => {
this.inputRef.current.focus();
}
render() {
return (
<div>
<input type="text" ref={this.inputRef} />
<button onClick={this.focusTextInput}>聚焦輸入框</button>
</div>
);
}
}
這個組件讓我們可以在點擊按鈕時程序化地聚焦輸入框。
2. 觸發命令式動畫
class Animator extends React.Component {
constructor(props) {
super(props);
this.elementRef = React.createRef();
}
animate = () => {
this.elementRef.current.classList.add('animated');
}
render() {
return (
<div>
<div ref={this.elementRef}>動畫我!</div>
<button onClick={this.animate}>開始動畫</button>
</div>
);
}
}
在這裡,我們使用 Ref 添加一個 CSS 類到元素,觸發動畫。
3. 與第三方 DOM 库集成
class MapComponent extends React.Component {
constructor(props) {
super(props);
this.mapRef = React.createRef();
}
componentDidMount() {
const mapLibrary = new FancyMapLibrary();
mapLibrary.createMap(this.mapRef.current);
}
render() {
return <div ref={this.mapRef} style={{width: '100%', height: '400px'}} />;
}
}
在這個例子中,我們使用 Ref 給第三方地圖庫訪問一個 DOM 節點,它可以在其中渲染地圖。
結論
Refs 是 React 中的強大工具,它們讓我們在必要時脫離聲明性範式。它們提供了一種直接訪問 DOM 節點或 React 元素的方式。然而,使用 Refs 應該謹慎。在大多數情況下,您可以通过 React 的聲明式 API 实现您需要的。但當您确实需要那麼一點額外的控制時,Refs 就會派上用場!
記住,能力越強,責任越大。謹慎使用 Refs,您的 React 應用程序會感謝您!
這裡是一個我們討論過的方法的快速參考表:
方法 | 描述 | 示例 |
---|---|---|
React.createRef() |
創建一個 ref 對象 | this.myRef = React.createRef(); |
ref 屬性 |
將一個 ref 附加到 React 元素 | <div ref={this.myRef} /> |
forwardRef |
讓函數組件能夠接收 refs | const FancyButton = React.forwardRef((props, ref) => ...) |
開心編程,願您的 Refs 永遠是最新的!
Credits: Image by storyset