From 614e3a3b873606e3c4adb7759de7a6564db6b841 Mon Sep 17 00:00:00 2001 From: CoderSerio Date: Sun, 9 Jul 2023 20:25:48 +0800 Subject: [PATCH 1/4] docs(cn): translate react-dom/client/createRoot into Chinese --- .../reference/react-dom/client/createRoot.md | 190 +++++++++--------- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md index a46d1f9d93..6e2d546456 100644 --- a/src/content/reference/react-dom/client/createRoot.md +++ b/src/content/reference/react-dom/client/createRoot.md @@ -4,7 +4,7 @@ title: createRoot -`createRoot` lets you create a root to display React components inside a browser DOM node. +`createRoot` 允许你在一个浏览器的 DOM 节点中创建一个根节点来显示你的 React 组件。 ```js const root = createRoot(domNode, options?) @@ -16,11 +16,11 @@ const root = createRoot(domNode, options?) --- -## Reference {/*reference*/} +## 参考资料 {/*reference*/} ### `createRoot(domNode, options?)` {/*createroot*/} -Call `createRoot` to create a React root for displaying content inside a browser DOM element. +调用 `createRoot` 来在一个浏览器 DOM 元素中创建一个根节点用于显示内容。 ```js import { createRoot } from 'react-dom/client'; @@ -29,104 +29,103 @@ const domNode = document.getElementById('root'); const root = createRoot(domNode); ``` -React will create a root for the `domNode`, and take over managing the DOM inside it. After you've created a root, you need to call [`root.render`](#root-render) to display a React component inside of it: +React 将会为 `domNode` 创建一个根节点,并控制其中的 DOM。在你已经创建了一个根节点之后,你需要调用 [`root.render`](#root-render) 来显示其中的一个 React 组件: ```js root.render(); ``` -An app fully built with React will usually only have one `createRoot` call for its root component. A page that uses "sprinkles" of React for parts of the page may have as many separate roots as needed. +对于一个完全用 React 构建的应用程序,通常会调用一个 `createRoot` 来创建它的根节点。而对于一个使用了“少量” React 来创建部分内容的应用程序,则要按具体需求来确定根节点的数量。 -[See more examples below.](#usage) +[参阅下方更多示例](#usage)。 -#### Parameters {/*parameters*/} +#### 参数 {/*parameters*/} -* `domNode`: A [DOM element.](https://developer.mozilla.org/zh-CN/docs/Web/API/Element) React will create a root for this DOM element and allow you to call functions on the root, such as `render` to display rendered React content. +* `domNode`:一个 [DOM 元素](https://developer.mozilla.org/zh-CN/docs/Web/API/Element)。React 将为这个 DOM 元素创建一个根节点然后允许你在这个根节点上调用函数,比如 `render` 来显示渲染的 React 内容。 -* **optional** `options`: An object with options for this React root. +* **可选** `options`:一个用于配置这个 React 根节点的对象。 - * **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. - * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. + * **可选** `onRecoverableError`:回调函数,在 React 从异常错误中恢复时自动调用。 + * **可选** `identifierPrefix`:一个 React 用来配合 [`useId`](/reference/react/useId) 生成 id 的字符串前缀。在同一个页面上使用多个根节点的场景下,这将能有效避免冲突。 -#### Returns {/*returns*/} +#### 返回值 {/*returns*/} -`createRoot` returns an object with two methods: [`render`](#root-render) and [`unmount`.](#root-unmount) +`createRoot` 返回一个带有两个方法的的对象,这两个方法是:[`render`](#root-render) 和 [`unmount`](#root-unmount)。 -#### Caveats {/*caveats*/} -* If your app is server-rendered, using `createRoot()` is not supported. Use [`hydrateRoot()`](/reference/react-dom/client/hydrateRoot) instead. -* You'll likely have only one `createRoot` call in your app. If you use a framework, it might do this call for you. -* When you want to render a piece of JSX in a different part of the DOM tree that isn't a child of your component (for example, a modal or a tooltip), use [`createPortal`](/reference/react-dom/createPortal) instead of `createRoot`. +#### 注意事项 {/*caveats*/} +* 如果你的应用程序是服务端渲染的,那么不能使用 `createRoot()`。请使用 [`hydrateRoot()`](/reference/react-dom/client/hydrateRoot) 替代它。 +* 在你的应用程序中,可能只调用了一次 `createRoot`。但如果你使用了框架,它可能已经自动帮你完成了这次调用。 +* 当你想要渲染一段 JSX,但是它存在于 DOM 树的其他位置,并非当前组件的子组件时(比如,一个弹窗或者提示框),使用 [`createPortal`](/reference/react-dom/createPortal) 替代 `createRoot`。 --- ### `root.render(reactNode)` {/*root-render*/} -Call `root.render` to display a piece of [JSX](/learn/writing-markup-with-jsx) ("React node") into the React root's browser DOM node. +调用 `root.render` 来将一段 [JSX](/learn/writing-markup-with-jsx) (“React 节点”)在 React 的根节点中渲染为 DOM 节点从而能够显示。 ```js root.render(); ``` -React will display `` in the `root`, and take over managing the DOM inside it. +React 将会在 `根节点` 中显示 `` 组件,并且控制组件中的 DOM。 -[See more examples below.](#usage) +[参阅下方查看更多示例](#usage)。 -#### Parameters {/*root-render-parameters*/} +#### 参数 {/*root-render-parameters*/} -* `reactNode`: A *React node* that you want to display. This will usually be a piece of JSX like ``, but you can also pass a React element constructed with [`createElement()`](/reference/react/createElement), a string, a number, `null`, or `undefined`. +* `reactNode`:一个你想要显示的 **React 节点**。它总是一段 JSX,就像 ``,但是你也总是可以传递一个 [`createElement()`](/reference/react/createElement) 构造的 React 元素、一个字符串、一个数字、`null` 或者 `undefined`。 -#### Returns {/*root-render-returns*/} +#### 返回值 {/*root-render-returns*/} -`root.render` returns `undefined`. +`root.render` 返回 `undefined`。 -#### Caveats {/*root-render-caveats*/} +#### 注意事项 {/*root-render-caveats*/} -* The first time you call `root.render`, React will clear all the existing HTML content inside the React root before rendering the React component into it. +* 首次调用 `root.render` 时,React 先会清空根节点中所有已经存在的 HTML,然后才会渲染 React 组件。 -* If your root's DOM node contains HTML generated by React on the server or during the build, use [`hydrateRoot()`](/reference/react-dom/client/hydrateRoot) instead, which attaches the event handlers to the existing HTML. +* 如果你的根节点包含了由 React 在构建期间通过服务端渲染生成的 HTML 内容,请使用 [`hydrateRoot()`](/reference/react-dom/client/hydrateRoot) 替代这个方法,这样才能把事件处理程序和现有的 HTML 绑定。 -* If you call `render` on the same root more than once, React will update the DOM as necessary to reflect the latest JSX you passed. React will decide which parts of the DOM can be reused and which need to be recreated by ["matching it up"](/learn/preserving-and-resetting-state) with the previously rendered tree. Calling `render` on the same root again is similar to calling the [`set` function](/reference/react/useState#setstate) on the root component: React avoids unnecessary DOM updates. +如果你在一个根节点上多次调用了 `render`,React 仍然会更新 DOM,这样才能保证显示的内容是最新的。React 将会筛选出可复用的部分和需要更新的部分,对于需要更新的部分,是 React 通过与之前渲染的树进行 [“比较”](/learn/preserving-and-resetting-state) 得到的。在同一个根节点上再次调用 `render` 就和在根节点上调用 [`set` 函数](/reference/react/useState#setstate) 类似:React 会避免没有必要的 DOM 更新。 --- ### `root.unmount()` {/*root-unmount*/} -Call `root.unmount` to destroy a rendered tree inside a React root. +调用 `root.unmount` 来销毁 React 根节点中的一个已经渲染的树。 ```js root.unmount(); ``` -An app fully built with React will usually not have any calls to `root.unmount`. +通常情况下,一个完全由 React 构建的应用程序不会调用 `root.unmount`。 -This is mostly useful if your React root's DOM node (or any of its ancestors) may get removed from the DOM by some other code. For example, imagine a jQuery tab panel that removes inactive tabs from the DOM. If a tab gets removed, everything inside it (including the React roots inside) would get removed from the DOM as well. In that case, you need to tell React to "stop" managing the removed root's content by calling `root.unmount`. Otherwise, the components inside the removed root won't know to clean up and free up global resources like subscriptions. +这个方法适用的场景是,你的 React 根节点中的 DOM 节点(或者它的任何一个父级节点)被除了这个方法以外的代码移除了。举个例子,试想在一个 jQuery 选项卡面板中,非活跃状态的选项卡的 DOM 结构将被移除。一个标签页被移除时,它内部的所有内容(包括 React 根节点)也将会从 DOM 树移除。在这种情况下,你才需要调用 `root.unmount` 来通知 React “停止”控制已经被移除的根节点的内容。否则,被移除的根节点的内部组件就不能及时释放消息订阅等资源。 -Calling `root.unmount` will unmount all the components in the root and "detach" React from the root DOM node, including removing any event handlers or state in the tree. +调用 `root.unmout` 将卸载根节点内的所有组件,该根节点上的 React 将被剥离,即所有事件处理程序以及组件树上的状态将被移除。 +#### 参数 {/*root-unmount-parameters*/} -#### Parameters {/*root-unmount-parameters*/} +`root.unmount` 不接收任何参数。 -`root.unmount` does not accept any parameters. +#### 返回值 {/*root-unmount-returns*/} -#### Returns {/*root-unmount-returns*/} +`root.unmount` 返回 `undefined`。 -`root.unmount` returns `undefined`. +#### 注意事项 {/*root-unmount-caveats*/} -#### Caveats {/*root-unmount-caveats*/} +* 调用 `root.unmout` 将卸载根节点内的所有组件,该根节点上的 React 将被剥离,即所有事件处理程序以及组件树上的状态将被移除。 -* Calling `root.unmount` will unmount all the components in the tree and "detach" React from the root DOM node. - -* Once you call `root.unmount` you cannot call `root.render` again on the same root. Attempting to call `root.render` on an unmounted root will throw a "Cannot update an unmounted root" error. However, you can create a new root for the same DOM node after the previous root for that node has been unmounted. +* 一旦你调用了 `root.unmout`,你就不能在该根节点上调用 `root.render`。在一个已经卸载的根节点上尝试调用 `root.render` 将会抛出异常错误信息“无法更新一个未挂载的根节点(Cannot update an unmouted root)”。不过,你可以在卸载一个根节点后又重新创建它。 --- -## Usage {/*usage*/} +## 使用方式 {/*usage*/} -### Rendering an app fully built with React {/*rendering-an-app-fully-built-with-react*/} +### 渲染一个完全由 React 构建的应用 {/*rendering-an-app-fully-built-with-react*/} -If your app is fully built with React, create a single root for your entire app. +如果你的应用程序是完全由 React 构建的,那么请为整个应用程序创建全局唯一的一个根节点。 ```js [[1, 3, "document.getElementById('root')"], [2, 4, ""]] import { createRoot } from 'react-dom/client'; @@ -135,10 +134,10 @@ const root = createRoot(document.getElementById('root')); root.render(); ``` -Usually, you only need to run this code once at startup. It will: +通常情况下,在项目启动阶段,你只需要运行下面的代码。它将会: -1. Find the browser DOM node defined in your HTML. -2. Display the React component for your app inside. +1. 获取 HTML 中定义的DOM 节点。 +2. 在该 DOM 节点中显示 React 组件 @@ -147,7 +146,7 @@ Usually, you only need to run this code once at startup. It will: My app - +
@@ -168,7 +167,7 @@ import { useState } from 'react'; export default function App() { return ( <> -

Hello, world!

+

你好,世界!

); @@ -178,7 +177,7 @@ function Counter() { const [count, setCount] = useState(0); return ( ); } @@ -186,35 +185,35 @@ function Counter() {
-**If your app is fully built with React, you shouldn't need to create any more roots, or to call [`root.render`](#root-render) again.** +**如果你的应用程序完全由 React 构建,你仅应该创建全局唯一的一个根节点,并只调用一次 [`root.render`](#root-render)**。 -From this point on, React will manage the DOM of your entire app. To add more components, [nest them inside the `App` component.](/learn/importing-and-exporting-components) When you need to update the UI, each of your components can do this by [using state.](/reference/react/useState) When you need to display extra content like a modal or a tooltip outside the DOM node, [render it with a portal.](/reference/react-dom/createPortal) +从这时起,React 将会控制你整个应用程序的 DOM。如果要添加更多组件,[可以将它们嵌套进 `App` 组件中](/learn/importing-and-exporting-components)。如果你需要更新视图,每一个组件都可以通过使用 [状态](/reference/react/useState) 做到这一点。如果你需要额外显示一些在这个 DOM 节点之外的内容,比如一个弹窗或者提示框,那么可以 [使用 portal 进行渲染](/reference/react-dom/createPortal)。 -When your HTML is empty, the user sees a blank page until the app's JavaScript code loads and runs: +当你的 HTML 为空时,用户将会看一个空白的页面,直到应用程序中的 JavaScript 代码加载并运行: ```html
``` -This can feel very slow! To solve this, you can generate the initial HTML from your components [on the server or during the build.](/reference/react-dom/server) Then your visitors can read text, see images, and click links before any of the JavaScript code loads. We recommend [using a framework](/learn/start-a-new-react-project#production-grade-react-frameworks) that does this optimization out of the box. Depending on when it runs, this is called *server-side rendering (SSR)* or *static site generation (SSG).* +这个过程太慢了!要解决这个问题,你可以在[服务端或者应用构建期间](/reference/react-dom/server),通过组件生成一些初始 HTML,这样一来,在 JavaScript 加载之前,用户就能看到一些文字、图片,也能点击链接。我们推荐 [使用一个框架](/learn/start-a-new-react-project#production-grade-react-frameworks),通过其开箱即用的能力轻易地完成这个优化。根据框架运行的时机,分为 **服务端渲染(SSR)** 和 **静态站点生成(SSG)**。
-**Apps using server rendering or static generation must call [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) instead of `createRoot`.** React will then *hydrate* (reuse) the DOM nodes from your HTML instead of destroying and re-creating them. +**使用了服务端渲染或者静态站点生成的应用程序,必须调用 [`hydrateRoot`](/reference/react-dom/client/hydrateRoot) 而不是 `createRoot`**。调用后,React 将会 **hydrate** (复用) HTML 中的 DOM 节点,而不是销毁后重新创建它们。 --- -### Rendering a page partially built with React {/*rendering-a-page-partially-built-with-react*/} +### 渲染一个部分由 React 构建的应用 {/*rendering-a-page-partially-built-with-react*/} -If your page [isn't fully built with React](/learn/add-react-to-an-existing-project#using-react-for-a-part-of-your-existing-page), you can call `createRoot` multiple times to create a root for each top-level piece of UI managed by React. You can display different content in each root by calling [`root.render`.](#root-render) +如果你的页面 [不完全是 React 构建的](/learn/add-react-to-an-existing-project#using-react-for-a-part-of-your-existing-page),你可以多次调用 `createRoot` 为每一个由 React 管理的顶级视图片段,即一段 DOM 中的顶级节点,创建一个根节点。你可以在每一个根节点中调用 [`root.render`](#root-render) 来显示不同的内容。 -Here, two different React components are rendered into two DOM nodes defined in the `index.html` file: +这样依赖,两个不同的 React 组件分别在同一个文件 `index.html` 内定义的两个 DOM 节点中被渲染: @@ -225,7 +224,7 @@ Here, two different React components are rendered into two DOM nodes defined in
-

This paragraph is not rendered by React (open index.html to verify).

+

这一段不会被 React 渲染(可以打开 index.html 验证这一点)。

@@ -268,8 +267,8 @@ export function Comments() { return ( <>

Comments

- - + + ); } @@ -288,28 +287,29 @@ nav ul li { display: inline-block; margin-right: 20px; }
-You could also create a new DOM node with [`document.createElement()`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createElement) and add it to the document manually. +你也可以通过 [`document.createElement()`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createElement) 创建一个新的 DOM 节点然后手动将其加入页面文档之中。 + ```js const domNode = document.createElement('div'); const root = createRoot(domNode); root.render(); -document.body.appendChild(domNode); // You can add it anywhere in the document +document.body.appendChild(domNode); // 你可以把它加入到页面文档的任何位置 ``` -To remove the React tree from the DOM node and clean up all the resources used by it, call [`root.unmount`.](#root-unmount) +调用 [`root.unmount`](#root-unmount) 将从 DOM 节点移除这个 React 树并清除它使用的资源。 ```js root.unmount(); ``` -This is mostly useful if your React components are inside an app written in a different framework. +如果你的 React 组件是处于一个由不同框架构建的应用程序之中时,那么这个方法将会非常有用。 --- -### Updating a root component {/*updating-a-root-component*/} +### 更新一个根组件 {/*updating-a-root-component*/} -You can call `render` more than once on the same root. As long as the component tree structure matches up with what was previously rendered, React will [preserve the state.](/learn/preserving-and-resetting-state) Notice how you can type in the input, which means that the updates from repeated `render` calls every second in this example are not destructive: +你可以在同一个根节点上多次调用 `render`。只要当前的组件树结构与之前渲染的结果是一致的,React 将会 [保存这些状态](/learn/preserving-and-resetting-state)。仔细思考一下,为什么你能在输入框中正常输入?正如下方的示例,在每一秒中内多次重复调用 `render` 后发生的更新,是非破坏性的: @@ -331,8 +331,8 @@ setInterval(() => { export default function App({counter}) { return ( <> -

Hello, world! {counter}

- +

你好,世界!{counter}

+ ); } @@ -340,14 +340,14 @@ export default function App({counter}) {
-It is uncommon to call `render` multiple times. Usually, your components will [update state](/reference/react/useState) instead. +多次调用 `render` 是一个不常见的事情。通常情况下,你的组件将通过 [更新状态](/reference/react/useState) 达到同样的效果。 --- -## Troubleshooting {/*troubleshooting*/} +## 错误排查 {/*troubleshooting*/} -### I've created a root, but nothing is displayed {/*ive-created-a-root-but-nothing-is-displayed*/} +### 我已经创建了一个根节点,但是页面没有显示任何内容 {/*ive-created-a-root-but-nothing-is-displayed*/} -Make sure you haven't forgotten to actually *render* your app into the root: +确保你没有忘记在根节点上 **渲染** 你的应用程序: ```js {5} import { createRoot } from 'react-dom/client'; @@ -357,63 +357,63 @@ const root = createRoot(document.getElementById('root')); root.render(); ``` -Until you do that, nothing is displayed. +在你进行渲染之前,页面不会显示任何内容。 --- -### I'm getting an error: "Target container is not a DOM element" {/*im-getting-an-error-target-container-is-not-a-dom-element*/} +### 我得到了一个异常报错信息:“目标容器不是一个 DOM 元素(Target container is not a DOM element)” {/*im-getting-an-error-target-container-is-not-a-dom-element*/} -This error means that whatever you're passing to `createRoot` is not a DOM node. +这个异常错误即字面意思,你传递给 `createRoot` 的内容不是一个 DOM 元素。 -If you're not sure what's happening, try logging it: +如果你不确定发生了什么,试着在控制台打印它: ```js {2} const domNode = document.getElementById('root'); -console.log(domNode); // ??? +console.log(domNode); // ??? const root = createRoot(domNode); root.render(); ``` +举个例子,如果 `domNode` 是 `null`,这意味着 For example, if `domNode` is `null`, it means that [`getElementById`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/getElementById) 返回了 `null`。这意味着你在调用这个方法的时候,页面文档内并不存在指定的 id 对应的元素,于是就出现了这个问题。这里有一些可能的原因: -For example, if `domNode` is `null`, it means that [`getElementById`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/getElementById) returned `null`. This will happen if there is no node in the document with the given ID at the time of your call. There may be a few reasons for it: +1. 你使用的 id 可能和 HTML 文件中的 id 不同。请检查一下你的拼写是否正确! +2. 打包构建产物的 HTML 文件中的 `