Skip to content
72 changes: 36 additions & 36 deletions src/content/reference/react/Fragment.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ title: <Fragment> (<>...</>)

`<Fragment>` 通常使用 `<>...</>` 代替,它们都允许你在不添加额外节点的情况下将子元素组合。

<Canary> Fragments can also accept refs, which enable interacting with underlying DOM nodes without adding wrapper elements. See reference and usage below.</Canary>
<Canary>Fragment 也可以接收 ref,使你能够与底层 DOM 节点交互,而无需添加额外的包装元素。参见下方的参考和用法。</Canary>

```js
<>
Expand All @@ -30,41 +30,41 @@ title: <Fragment> (<>...</>)
#### 参数 {/*props*/}

- **可选** `key`:列表中 `<Fragment>` 的可以拥有 [keys](/learn/rendering-lists#keeping-list-items-in-order-with-key)。
- <CanaryBadge /> **optional** `ref`: A ref object (e.g. from [`useRef`](/reference/react/useRef)) or [callback function](/reference/react-dom/components/common#ref-callback). React provides a `FragmentInstance` as the ref value that implements methods for interacting with the DOM nodes wrapped by the Fragment.
- <CanaryBadge /> **可选** `ref`:一个 ref 对象(例如来自 [`useRef`](/reference/react/useRef))或[回调函数](/reference/react-dom/components/common#ref-callback)React 提供一个 `FragmentInstance` 作为 ref 值,该对象实现了用于与 Fragment 包裹的 DOM 节点交互的方法。

### <CanaryBadge /> FragmentInstance {/*fragmentinstance*/}

When you pass a ref to a fragment, React provides a `FragmentInstance` object with methods for interacting with the DOM nodes wrapped by the fragment:
当你将 ref 传递给 Fragment 时,React 会提供一个 `FragmentInstance` 对象,其中包含用于与 Fragment 包裹的 DOM 节点进行交互的方法:

**Event handling methods:**
- `addEventListener(type, listener, options?)`: Adds an event listener to all first-level DOM children of the Fragment.
- `removeEventListener(type, listener, options?)`: Removes an event listener from all first-level DOM children of the Fragment.
- `dispatchEvent(event)`: Dispatches an event to a virtual child of the Fragment to call any added listeners and can bubble to the DOM parent.
**事件处理方法**:
- `addEventListener(type, listener, options?)`:向 Fragment 的所有第一级 DOM 子元素添加事件监听器。
- `removeEventListener(type, listener, options?)`:从 Fragment 的所有第一级 DOM 子元素中移除事件监听器。
- `dispatchEvent(event)`:向 Fragment 的虚拟子元素分发事件以调用任何已添加的监听器,并且可以冒泡到 DOM 父元素。

**Layout methods:**
- `compareDocumentPosition(otherNode)`: Compares the document position of the Fragment with another node.
- If the Fragment has children, the native `compareDocumentPosition` value is returned.
- Empty Fragments will attempt to compare positioning within the React tree and include `Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC`.
- Elements that have a different relationship in the React tree and DOM tree due to portaling or other insertions are `Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC`.
- `getClientRects()`: Returns a flat array of `DOMRect` objects representing the bounding rectangles of all children.
- `getRootNode()`: Returns the root node containing the Fragment's parent DOM node.
**布局方法**:
- `compareDocumentPosition(otherNode)`:比较 Fragment 与另一个节点的文档位置。
- 如果 Fragment 有子元素,则返回原生的 `compareDocumentPosition` 值。
- 空的 Fragment 会尝试在 React 树中比较位置,并包含 `Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC`
- 由于 portal 或其他插入方式导致在 React 树和 DOM 树中关系不同的元素,将返回 `Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC`
- `getClientRects()`:返回一个扁平数组,包含表示所有子元素边界矩形的 `DOMRect` 对象。
- `getRootNode()`:返回包含 Fragment DOM 节点的根节点。

**Focus management methods:**
- `focus(options?)`: Focuses the first focusable DOM node in the Fragment. Focus is attempted on nested children depth-first.
- `focusLast(options?)`: Focuses the last focusable DOM node in the Fragment. Focus is attempted on nested children depth-first.
- `blur()`: Removes focus if `document.activeElement` is within the Fragment.
**焦点管理方法**:
- `focus(options?)`:聚焦 Fragment 中的第一个可聚焦 DOM 节点。会以深度优先的方式尝试聚焦嵌套的子元素。
- `focusLast(options?)`:聚焦 Fragment 中的最后一个可聚焦 DOM 节点。会以深度优先的方式尝试聚焦嵌套的子元素。
- `blur()`:如果 `document.activeElement` Fragment 内部,则移除焦点。

**Observer methods:**
- `observeUsing(observer)`: Starts observing the Fragment's DOM children with an IntersectionObserver or ResizeObserver.
- `unobserveUsing(observer)`: Stops observing the Fragment's DOM children with the specified observer.
**观察者方法**:
- `observeUsing(observer)`:使用 IntersectionObserver 或 ResizeObserver 开始观察 FragmentDOM 子元素。
- `unobserveUsing(observer)`:停止使用指定的观察者观察 FragmentDOM 子元素。

#### 注意事项 {/*caveats*/}

- 如果你要传递 `key` 给一个 `<Fragment>`,你不能使用 `<>...</>`,你必须从 `'react'` 中导入 `Fragment` 且表示为`<Fragment key={yourKey}>...</Fragment>`。

- 当你要从 `<><Child /></>` 转换为 `[<Child />]` 或 `<><Child /></>` 转换为 `<Child />`,React 并不会[重置 state](/learn/preserving-and-resetting-state)。这个规则只在一层深度的情况下生效,如果从 `<><><Child /></></>` 转换为 `<Child />` 则会重置 state。在[这里](https://gist.github.com/clemmy/b3ef00f9507909429d8aa0d3ee4f986b)查看更详细的介绍。

- <CanaryBadge /> If you want to pass `ref` to a Fragment, you can't use the `<>...</>` syntax. You have to explicitly import `Fragment` from `'react'` and render `<Fragment ref={yourRef}>...</Fragment>`.
- <CanaryBadge /> 如果你想向 Fragment 传递 `ref`,则不能使用 `<>...</>` 语法。你必须显式地从 `'react'` 中导入 `Fragment` 并渲染 `<Fragment ref={yourRef}>...</Fragment>`

---

Expand Down Expand Up @@ -93,8 +93,8 @@ function Post() {
export default function Blog() {
return (
<>
<Post title="An update" body="It's been a while since I posted..." />
<Post title="My new blog" body="I am starting a new blog!" />
<Post title="一则更新" body="距离我上次发帖已经有一段时间了..." />
<Post title="我的新博客" body="我开始了新的博客!" />
</>
)
}
Expand Down Expand Up @@ -162,7 +162,7 @@ function CloseDialog() {
);
return (
<AlertDialog buttons={buttons}>
Are you sure you want to leave this page?
你确定要离开此页面吗?
</AlertDialog>
);
}
Expand All @@ -178,9 +178,9 @@ function CloseDialog() {
function DateRangePicker({ start, end }) {
return (
<>
From
<DatePicker date={start} />
to
<DatePicker date={end} />
</>
);
Expand Down Expand Up @@ -242,9 +242,9 @@ function PostBody({ body }) {

---

### <CanaryBadge /> Using Fragment refs for DOM interaction {/*using-fragment-refs-for-dom-interaction*/}
### <CanaryBadge /> 使用 Fragment ref 进行 DOM 交互 {/*using-fragment-refs-for-dom-interaction*/}

Fragment refs allow you to interact with the DOM nodes wrapped by a Fragment without adding extra wrapper elements. This is useful for event handling, visibility tracking, focus management, and replacing deprecated patterns like `ReactDOM.findDOMNode()`.
Fragment ref 允许你与 Fragment 包裹的 DOM 节点进行交互,而无需添加额外的包装元素。这对于事件处理、可见性跟踪、焦点管理以及替代已弃用的模式(如 `ReactDOM.findDOMNode()`)非常有用。

```js
import { Fragment } from 'react';
Expand All @@ -262,9 +262,9 @@ function ClickableFragment({ children, onClick }) {
```
---

### <CanaryBadge /> Tracking visibility with Fragment refs {/*tracking-visibility-with-fragment-refs*/}
### <CanaryBadge /> 使用 Fragment ref 跟踪可见性 {/*tracking-visibility-with-fragment-refs*/}

Fragment refs are useful for visibility tracking and intersection observation. This enables you to monitor when content becomes visible without requiring the child Components to expose refs:
Fragment ref 对于可见性跟踪和交叉观察非常有用。这使你能够监控内容何时变为可见,而无需子组件暴露 ref:

```js {19,21,31-34}
import { Fragment, useRef, useLayoutEffect } from 'react';
Expand Down Expand Up @@ -293,7 +293,7 @@ function VisibilityObserverFragment({ threshold = 0.5, onVisibilityChange, child

function MyComponent() {
const handleVisibilityChange = (isVisible) => {
console.log('Component is', isVisible ? 'visible' : 'hidden');
console.log('组件', isVisible ? '可见' : '已隐藏');
};

return (
Expand All @@ -305,13 +305,13 @@ function MyComponent() {
}
```

This pattern is an alternative to Effect-based visibility logging, which is an anti-pattern in most cases. Relying on Effects alone does not guarantee that the rendered Component is observable by the user.
这种模式是基于 Effect 的可见性日志记录的替代方案,后者在大多数情况下是一种反模式。仅依赖 Effect 并不能保证渲染的组件对用户可见。

---

### <CanaryBadge /> Focus management with Fragment refs {/*focus-management-with-fragment-refs*/}
### <CanaryBadge /> 使用 Fragment ref 管理焦点 {/*focus-management-with-fragment-refs*/}

Fragment refs provide focus management methods that work across all DOM nodes within the Fragment:
Fragment ref 提供了焦点管理方法,可作用于 Fragment 内的所有 DOM 节点:

```js
import { Fragment, useRef } from 'react';
Expand All @@ -325,4 +325,4 @@ function FocusFragment({ children }) {
}
```

The `focus()` method focuses the first focusable element within the Fragment, while `focusLast()` focuses the last focusable element.
`focus()` 方法聚焦 Fragment 内的第一个可聚焦元素,而 `focusLast()` 聚焦最后一个可聚焦元素。
Loading
Loading