React的脱围机制

188 阅读3分钟

使用ref操作dom

开发React项目时,常常会遇到需要访问由React管理的DOM元素,例如--让一个节点获得焦点、滚动到它或测量它的尺寸和位置。在 React 中没有内置的方法来做这些事情,所以你需要一个指向 DOM 节点的 ref 来实现。

获取指向节点的 ref

要访问由 React 管理的 DOM 节点,首先,引入 useRef Hook:
import { useRef } from 'react';
然后,在组件中使用它声明一个 ref:
const myRef = useRef(null);
最后,将 ref 作为 ref 属性值传递给想要获取的 DOM 节点的 JSX 标签:
<div ref={myRef}>
useRef Hook 返回一个对象,该对象有一个名为 current 的属性。最初,myRef.currentnull。当 React 为这个 <div> 创建一个 DOM 节点时,React 会把对该节点的引用放入 myRef.current。然后,你可以从 事件处理器 访问此 DOM 节点,并使用在其上定义的内置浏览器 API

// 可以使用任意浏览器 API,例如:  
myRef.current.scrollIntoView();
示例: 使文本输入框获得焦点

在本例中,单击按钮将使输入框获得焦点:

import { useRef } from 'react';

export default function Form() {
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        聚焦输入框
      </button>
    </>
  );
}

要实现这一点:

  1. 使用 useRef Hook 声明 inputRef
  2. 像 <input ref={inputRef}> 这样传递它。这告诉 React 将这个 <input> 的 DOM 节点放入 inputRef.current
  3. 在 handleClick 函数中,从 inputRef.current 读取 input DOM 节点并使用 inputRef.current.focus() 调用它的 focus()
  4. 用 onClick 将 handleClick 事件处理器传递给 <button>
## 使用 refs 操作 DOM 的最佳实践

Refs 是一种脱围机制。你应该只在你必须“跳出 React”时使用它们。这方面的常见示例包括管理焦点、滚动位置或调用 React 未暴露的浏览器 API。

如果你坚持聚焦和滚动等非破坏性操作,应该不会遇到任何问题。但是,如果你尝试手动修改 DOM,则可能会与 React 所做的更改发生冲突。

使用 Effect 同步

有些组件需要与外部系统同步。例如,我们可能希望根据 React state 控制非 React 组件、设置服务器连接或在组件出现在屏幕上时发送分析日志。Effects 会在渲染后运行一些代码,以便可以将组件与 React 之外的某些系统同步。

如何编写 Effect

编写 Effect 需要遵循以下三个规则:

  1. 声明 Effect。默认情况下,Effect 会在每次 提交 后都会执行。
  2. 指定 Effect 依赖。大多数 Effect 应该按需执行,而不是在每次渲染后都执行。例如,淡入动画应该只在组件出现时触发。连接和断开服务器的操作只应在组件出现和消失时,或者切换聊天室时执行。文章将介绍如何通过指定依赖来控制如何按需执行。
  3. 必要时添加清理(cleanup)函数。有时 Effect 需要指定如何停止、撤销,或者清除它的效果。例如,“连接”操作需要“断连”,“订阅”需要“退订”,“获取”既需要“取消”也需要“忽略”。你将学习如何使用 清理函数 来做到这一切。

以下是具体步骤。

第一步:声明 Effect

首先在 React 中引入 useEffect Hook

import { useEffect } from 'react';

然后,在组件顶部调用它,并传入在每次渲染时都需要执行的代码:

function MyComponent() {

  useEffect(() => {

    // 每次渲染后都会执行此处的代码

  });

  return <div />;

}

每当你的组件渲染时,React 将更新屏幕,然后运行 useEffect 中的代码。换句话说,useEffect 会把这段代码放到屏幕更新渲染之后执行