說明
支持我們

參考

如同我們在第一章節所學,DOM 提供了一個命令式 API,它讓我們可以呼叫元素上的函式來進行變更。一個我們可能需要從 Preact 元件存取命令式 DOM API 的範例是自動將焦點移至輸入元素。

autoFocus 屬性(或 autofocus 特性)可以用於在第一次呈現時將焦點移至輸入,然而在某些情況下,我們會希望在特定時間或回應特定事件時將焦點移至輸入。

對於這些需要我們直接與 DOM 元素互動的情況,我們可以使用稱為「ref」的功能。ref 是具有 current 屬性的純 JavaScript 物件,指向任何值。JavaScript 物件是透過參照傳遞的,這表示任何有權存取 ref 物件的函式都可以使用 current 屬性取得或設定其值。Preact 不會追蹤 ref 物件的變更,因此它們可以用於在呈現期間儲存資訊,然後任何有權存取 ref 物件的函式都可以稍後存取這些資訊。

我們可以看到在不呈現任何內容的情況下,ref 功能的直接使用方式如下

import { createRef } from 'preact'

// create a ref:
const ref = createRef('initial value')
// { current: 'initial value' }

// read a ref's current value:
ref.current === 'initial value'

// update a ref's current value:
ref.current = 'new value'

// pass refs around:
console.log(ref) // { current: 'new value' }

ref 在 Preact 中之所以有用,是因為可以在呈現期間將 ref 物件傳遞給虛擬 DOM 元素,而 Preact 會將 ref 的值(其 current 屬性)設定為對應的 HTML 元素。設定後,我們可以使用 ref 的目前值來存取和修改 HTML 元素

import { createRef } from 'preact';

// create a ref:
const input = createRef()

// pass the ref as a prop on a Virtual DOM element:
render(<input ref={input} />, document.body)

// access the associated DOM element:
input.current // an HTML <input> element
input.current.focus() // focus the input!

不建議全域性使用 createRef(),因為多重呈現會覆寫 ref 的目前值。相反地,最好將 ref 儲存為類別屬性

import { createRef, Component } from 'preact';

export default class App extends Component {
  input = createRef()

  // this function runs after <App> is rendered
  componentDidMount() {
    // access the associated DOM element:
    this.input.current.focus();
  }

  render() {
    return <input ref={this.input} />
  }
}

對於函式元件,useRef() 鉤子提供一個方便的方式來建立一個 ref,並在後續渲染中存取同一個 ref。以下範例也顯示如何使用 useEffect() 鉤子在元件渲染後呼叫回呼函式,其中 ref 的目前值會設定為 HTML 輸入元素

import { useRef, useEffect } from 'preact/hooks';

export default function App() {
  // create or retrieve our ref:  (hook slot 0)
  const input = useRef()

  // the callback here will run after <App> is rendered:
  useEffect(() => {
    // access the associated DOM element:
    input.current.focus()
  }, [])

  return <input ref={input} />
}

請記住,ref 不僅限於儲存 DOM 元素。它們可以用於在元件渲染之間儲存資訊,而不會設定會導致額外渲染的狀態。我們將在後面的章節中看到一些用途。

試試看!

現在讓我們透過建立一個按鈕來實作,當按鈕被按一下時,會透過 ref 存取輸入欄位並將焦點移至該欄位。

載入中...