这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战
翻译自:beta.reactjs.org/learn/manip…
因为 React 已经根据 render 的输出处理了 DOM 结构,所以你的组件不经常需要操作 DOM。然而,有的时候你可能需要操作 React 管理的 DOM 元素,比如,将焦点放到一个节点上,滚动到这个节点,或者去计算它的宽和高。React 中没有内置的方法去做这些事情,所以你将会需要 ref 去指向这个 DOM 节点。
这个系列的文章你将会学到:
- 如何使用 ref 属性访问由 React 管理的 DOM 节点
- 如何将 JSX 的
ref属性关联到useRef钩子 - 如何访问其他组件的 DOM 节点
- 在哪种情况下,修改 React 管理的 DOM 是安全的
关于 ref 相关的介绍和例子,可以看我前面一个系列的文章 useRef 简单易懂解析
系列文章
如何使用 ref 操作 DOM?(一)使用 ref 访问 DOM 节点
示例:input 聚焦
在本例中,单击按钮将聚焦 input:
import { useRef } from 'react';
export default function Form() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>
Focus the input
</button>
</>
);
}
要实现这一点:
- 用
useRef钩子声明inputRef。 - 将
inputRef作为<input ref={inputRef}>传递。这告诉 React 将这个<input>的 DOM 节点放入inputRef.current中。 - 在
handleClick函数中,从inputRef.current读取 input 的 DOM 节点,并使用inputRef.current.focus()对其调用focus()。 - 使用
onClick将handleClick事件处理程序传递给<button>。
虽然 DOM 操作是 refs 最常见的用例,但 useRef Hook 可以用于在 React 之外存储其他东西,比如计时器 id。与 state 类似,refs 在呈现之间保持不变。您甚至可以将 refs 视为状态变量,当您设置它们时,它们不会触发重新 render
示例:滚动到一个元素
一个组件中可以有多个引用。在这个例子中,有一个由三个图像和三个按钮组成的轮播,通过调用浏览器 scrollIntoView() 方法在相应的 DOM 节点上将它们居中显示在视口中:
import { useRef } from 'react';
export default function CatFriends() {
const firstCatRef = useRef(null);
const secondCatRef = useRef(null);
const thirdCatRef = useRef(null);
function handleScrollToFirstCat() {
firstCatRef.current.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'center'
});
}
function handleScrollToSecondCat() {
secondCatRef.current.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'center'
});
}
function handleScrollToThirdCat() {
thirdCatRef.current.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'center'
});
}
return (
<>
<nav>
<button onClick={handleScrollToFirstCat}>
Tom
</button>
<button onClick={handleScrollToSecondCat}>
Maru
</button>
<button onClick={handleScrollToThirdCat}>
Jellylorum
</button>
</nav>
<div>
<ul>
<li>
<img
src="https://placekitten.com/g/200/200"
alt="Tom"
ref={firstCatRef}
/>
</li>
<li>
<img
src="https://placekitten.com/g/300/200"
alt="Maru"
ref={secondCatRef}
/>
</li>
<li>
<img
src="https://placekitten.com/g/250/200"
alt="Jellylorum"
ref={thirdCatRef}
/>
</li>
</ul>
</div>
</>
);
}