引用
正如我们在第一章中了解到的,DOM 提供了一个命令式 API,它允许我们通过调用元素上的函数来进行更改。我们需要从 Preact 组件访问命令式 DOM API 的一个示例是自动将焦点移动到输入元素。
autoFocus
属性(或 autofocus
属性)可用于在首次呈现输入时对其进行聚焦,但是,在某些情况下,我们希望在特定时间或响应特定事件将焦点移动到输入。
对于我们需要直接与 DOM 元素交互的这些情况,我们可以使用称为“引用”的功能。引用是一个带有 current
属性的普通 JavaScript 对象,该属性指向任何值。JavaScript 对象通过引用传递,这意味着任何可以访问引用对象的函数都可以使用 current
属性获取或设置其值。Preact 不会跟踪对引用对象的更改,因此它们可用于在渲染期间存储信息,然后任何可以访问引用对象的函数都可以稍后访问这些信息。
我们可以看到在不呈现任何内容的情况下直接使用引用功能是什么样子的
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' }
引用在 Preact 中很有用的原因是可以在渲染期间将引用对象传递给虚拟 DOM 元素,Preact 会将引用的值(其 current
属性)设置为相应的 HTML 元素。设置后,我们可以使用引用的当前值来访问和修改 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 访问输入字段,从而使输入字段获得焦点。