Skip to content

Commit ee52d3a

Browse files
committed
revise
1 parent b369632 commit ee52d3a

File tree

5 files changed

+76
-73
lines changed

5 files changed

+76
-73
lines changed

README-zh_CN.md

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,38 @@
1-
# Building a custom React renderer
1+
# 创建一个自定义 React 渲染器
22

33
[![Build Status](https://travis-ci.org/nitin42/Making-a-custom-React-renderer.svg?branch=master)](https://travis-ci.org/nitin42/Making-a-custom-React-renderer)
44

5+
[English](./README.md) | 简体中文
6+
57
> 让我们创建一个自定义的 React 渲染器 😎
68
79
<p align="center">
810
<img src="https://cdn.filestackcontent.com/5KdzhvGRG61WMQhBa1Ql" width="630" height="350">
911
</p>
1012

11-
## Introduction
13+
## 介绍
1214

13-
这是一个关于如何创建自定义 React 渲染器并将组件渲染到你需要的宿主环境的教程。教程分为三部分 ——
15+
这是一个关于如何创建一个自定义 React 渲染器并将所有内容渲染到你的目标宿主环境中的教程。教程分为三部分 ——
1416

1517
* **第一部分** - 创建一个 React 调度器(使用 [`react-reconciler`](https://github.com/facebook/react/tree/master/packages/react-reconciler) 包)。
1618

17-
* **第二部分** - Creating a public interface to the reconciler i.e "Renderer".
19+
* **第二部分** - 我们将创建一个用于调度器的公开方法。
1820

19-
* **第三部分** - Creating a render method to flush everything to the host environment we need.
21+
* **第三部分** - 创建渲染方法来将所有创建的组件实例渲染到我们的目标宿主环境中。
2022

21-
## Brief
23+
## 概要
2224

23-
### [第一部分](./part-one.md)
25+
### [第一部分](./part-one-zh_CN.md)
2426

2527
在第一部分,我们将使用 [`react-reconciler`](https://github.com/facebook/react/tree/master/packages/react-reconciler) 创建一个 React 调度器。我们将使用 Fiber 实现渲染器,因为它拥有优秀的用于创建自定义渲染器的 API。
2628

27-
### [第二部分](./part-two.md)
29+
### [第二部分](./part-two-zh_CN.md)
2830

29-
In part two, we will create a public interface to the reconciler i.e a renderer. We will create a custom method for `createElement` and will also architect the component API for our example.
31+
在第二部分,我们将创建一个用于调度器的公开方法。我们将创建一个自定义 `createElement` 函数,还将为我们的示例构建组件 API
3032

31-
### [第三部分](./part-three.md)
33+
### [第三部分](./part-three-zh_CN.md)
3234

33-
In part three, we will create a render method which will render our input component.
35+
在第三部分,我们将创建渲染方法,用于渲染我们创建的组件实例。
3436

3537
## 我们将创建什么?
3638

@@ -56,26 +58,26 @@ doc.generate(output);
5658

5759
**事件**
5860

59-
`finalize` - It is fired after a stream has been generated successfully.
61+
`finalize` - 在流生成成功之后触发。
6062

61-
`error` - Fired when there are any errors
63+
`error` - 在发生异常时触发。
6264

6365
## 运行这个项目
6466

65-
```
67+
```bash
6668
git clone https://github.com/nitin42/Making-a-custom-React-renderer
6769
cd Making-a-custom-React-renderer
6870
yarn install
6971
yarn example
7072
```
7173

72-
After you run `yarn example`, a docx file will be generated in the [demo](./demo) folder.
74+
运行 `yarn example` 后,会在 [demo](./demo) 文件夹下生成一个 docx 文件。
7375

74-
## Contributing
76+
## 贡献
7577

76-
Suggestions to improve the tutorial are welcome 😃.
78+
欢迎提出改进教程的建议😃。
7779

78-
**If you've completed the tutorial successfully, you can either watch/star this repo or follow me on [twitter](https://twitter.com/NTulswani) for more updates.**
80+
**如果您已成功完成本教程,您可以 watch 或 star 此代码库或在 [twitter](https://twitter.com/NTulswani) 上关注我以获取最新的消息。**
7981

8082
<a target='_blank' rel='nofollow' href='https://app.codesponsor.io/link/FCRW65HPiwhNtebDx2tTc53E/nitin42/Making-a-custom-React-renderer'>
8183
<img alt='Sponsor' width='888' height='68' src='https://app.codesponsor.io/embed/FCRW65HPiwhNtebDx2tTc53E/nitin42/Making-a-custom-React-renderer.svg' />

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
[![Build Status](https://travis-ci.org/nitin42/Making-a-custom-React-renderer.svg?branch=master)](https://travis-ci.org/nitin42/Making-a-custom-React-renderer)
44

5+
English | [简体中文](./README-zh_CN.md)
6+
57
> Let's make a custom React renderer 😎
68
79
<p align="center">

part-one-zh_CN.md

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
# 第一部分
22

3-
这是教程的第一部分。这是教程中最重要的部分,你将在其中了解 Fiber 及其结构与字段的详细说明,为渲染器创建与宿主环境相关的配置并将渲染器注入开发者工具中
3+
这是教程的第一部分,也是教程最重要的部分,你将在其中了解 Fiber 及其结构与属性的详细说明,为你的渲染器创建宿主环境配置并将渲染器注入开发工具中
44

5-
在这个部分,我们将使用 [`react-reconciler`](https://github.com/facebook/react/tree/master/packages/react-reconciler) 包创建一个 React 调度器。我们将使用 Fiber 实现渲染器。初期,React 使用 **栈渲染器**它是在传统的 JavaScript 栈上实现。另一方面,Fiber 受代数效应和函数式思维的影响。它可以被认为是一个 JavaScript 对象,其中包含组件、输入和输出的信息
5+
在这个部分,我们将使用 [`react-reconciler`](https://github.com/facebook/react/tree/master/packages/react-reconciler) 包创建一个 React 调度器。我们将使用 Fiber 实现渲染器。起初,React 使用 **栈渲染器**它是在 JavaScript 的调用栈上实现。另一方面,Fiber 受代数效应和函数式编程思维的影响。它可以被认为是一个包含组件输入和输出的信息的 JavaScript 对象。
66

7-
在我们继续之前,我建议你阅读 [这个](https://github.com/acdlite/react-fiber-architecture) 文档 [Andrew Clark](https://twitter.com/ acdlite?lang=en)。这会让你容易些
7+
在我们继续之前,我建议你阅读由 [Andrew Clark](https://twitter.com/acdlite?lang=en) 写的 [这篇](https://github.com/acdlite/react-fiber-architecture) 文章。这会让你更容易理解本教程
88

99
让我们开始!
1010

11-
我们将首先安装这些依赖
11+
我们首先安装这些依赖
1212

1313
```bash
1414
npm install react-reconciler fbjs
1515
```
1616

17-
让我们从 `react-reconciler` 导入 `Reconciler`然后导入其它模块
17+
让我们从 `react-reconciler` 引入 `Reconciler`接着引入其它模块
1818

1919
```js
2020
import Reconciler from 'react-reconciler';
@@ -23,9 +23,9 @@ import emptyObject from 'fbjs/lib/emptyObject';
2323
import { createElement } from './utils/createElement';
2424
```
2525

26-
注意我们还导入了 `createElement` 函数。别担心,我们稍后会实现它。
26+
注意我们还引入了 `createElement` 函数。别担心,我们稍后会实现它。
2727

28-
我们将传入 **host config** 对象到 `Reconciler` 创建一个实例。在这个对象中,我们将定义一些可以被认为是渲染器生命周期的方法(更新、添加子组件、删除子组件、提交)。 React 将管理所有非宿主组件。
28+
我们传入 **host config** 对象到 `Reconciler` 中来创建一个它的实例。在这个对象中,我们将定义一些可以认为是渲染器生命周期的方法(更新、添加子组件、删除子组件、提交)。 React 将管理所有非宿主组件。
2929

3030
```js
3131
const WordRenderer = Reconciler({
@@ -70,7 +70,7 @@ const WordRenderer = Reconciler({
7070
},
7171

7272
getRootHostContext(rootInstance) {
73-
// 你可以使用此 'rootInstance' 从根传递数据
73+
// 你可以使用此 'rootInstance' 从根节点传递数据
7474
},
7575

7676
getChildHostContext() {
@@ -87,44 +87,43 @@ const WordRenderer = Reconciler({
8787
});
8888
```
8989

90-
让我们分析一下我们的 host config -
90+
让我们分析一下我们的宿主配置 -
9191

9292
**`createInstance`**
9393

94-
这个方法根据 `type``props``internalInstanceHandle` 创建一个组件实例
94+
这个方法根据 `type``props``internalInstanceHandle` 创建组件实例
9595

9696
例子 - 假设我们渲染如下内容,
9797

9898
```js
9999
<Text>Hello World</Text>
100100
```
101101

102-
`createInstance` 将返回元素的 `type` (' TEXT ')、`props` ( { children: 'Hello World' } )和根元素的实例(`WordDocument`)信息。
102+
`createInstance` 方法中将获得元素的 `type` (' TEXT ')、`props` ( { children: 'Hello World' } )和根元素的实例(`WordDocument`)信息。
103103

104104
**Fiber**
105105

106-
Fiber 是组件需要完成或已经完成的工作。最多,一个组件实例有两个 Fiber,已完成的 Fiber 和进行中的 Fiber。
106+
Fiber 是组件需要或已经完成的工作。最多,一个组件实例有两个 Fiber,已完成的 Fiber 和进行中的 Fiber。
107107

108-
`internalInstanceHandle` 包含的信息有 `tag``type``key``stateNode` 和工作完成后退回的 Fiber。这个对象(Fiber)未来包含的信息有 -
108+
`internalInstanceHandle` 包含的信息有 `tag``type``key``stateNode` 和工作完成后会退回去的 Fiber。这个对象(Fiber)包含的信息有 -
109109

110110
* **`tag`** - Fiber 的类型。
111-
* **`key`** - 子元素的唯一标识
112-
* **`type`** - 该 Fiber 关联的方法、类、模块
111+
* **`key`** - 子节点的唯一标识
112+
* **`type`** - 该 Fiber 关联的方法、类或模块
113113
* **`stateNode`** - 该 Fiber 关联的本地状态。
114114

115-
* **`return`** - 当前 Fiber 执行完毕后将要退回的 Fiber(父 Fiber)。
115+
* **`return`** - 当前 Fiber 执行完毕后将要回退回去的 Fiber(父 Fiber)。
116116
* **`child`** - `child``sibling``index` 表达 **单向列表数据结构**
117117
* **`sibling`**
118118
* **`index`**
119119
* **`ref`** - ref 最终用于关联这个节点。
120120

121-
* **`pendingProps`** - 该属性用于标签重载时
121+
* **`pendingProps`** - 该属性用于标签发生重载时
122122
* **`memoizedProps`** - 该属性用于创建输出。
123-
* **`updateQueue`** - 用于状态更新和回调的队列
123+
* **`updateQueue`** - 状态更新和回调的队列
124124
* **`memoizedState`** - 该状态用于创建输出。
125125

126-
* **`internalContextTag`** - 位运算数据结构。Fiber 使用位运算数据结构来保存有关 Fiber 及其子树的信息序列,该子树存储在相邻的计算机内存位置。该属性中的位用于确定属性的状态。称为标志的位域集合表示操作的结果或某些中间状态。React Fiber 使用 AsyncUpdates 标志来指示子树是否是异步的。
127-
* **`effectTag`** - 副作用标记。
126+
* **`subtreeFlags`** - 位标志。Fiber 使用位标志来保存有关 Fiber 及其子树的一些表示操作状态或某些中间状态。
128127
* **`nextEffect`** - 在单向链表中快速到下一个具有副作用的 Fiber。
129128
* **`firstEffect`** - 子树中有副作用的第一个(firstEffect)和最后一个(lastEffect)Fiber。重用此 Fiber 中已经完成的工作。
130129

@@ -139,7 +138,7 @@ Fiber 是组件需要完成或已经完成的工作。最多,一个组件实
139138

140139
**`appendInitialChild`**
141140

142-
它用于添加子组件。如果子组件包含在父组件中(例如:`Document`),那么我们将添加所有子组件到父组件中,否则我们将在父节点上创建一个名为 `document` 的属性并将所有子节点添加给它
141+
它用于添加子节点。如果子节点包含在父节点中(例如:`Document`),那么我们将添加所有子节点到父节点中,否则我们将在父节点上创建一个名为 `document` 的属性后添加所有子节点
143142

144143
例子 -
145144

@@ -149,15 +148,15 @@ const data = document.render(); // 返回输出
149148

150149
**`prepareUpdate`**
151150

152-
它计算实例的差异。即使 Fiber 暂停或中止对树的一部分渲染,也可以重用这项工作。
151+
它计算实例的差异。即使 Fiber 暂停或中止对树的部分渲染,也可以重用这项工作。
153152

154153
**`commitUpdate`**
155154

156155
提交更新或将计算的差异应用到宿主环境的节点 (WordDocument)。
157156

158157
**`commitMount`**
159158

160-
渲染器挂载宿主组件,但可能会在表单自动获得焦点之后进行一些工作。仅当没有当前或备用(alternate) Fiber 时才挂载宿主组件。
159+
渲染器挂载宿主节点,但可能会在表单自动获得焦点之后进行一些工作。仅当没有当前或备用(alternate) Fiber 时才挂载宿主组件。
161160

162161
**`hostContext`**
163162

@@ -177,47 +176,47 @@ const data = document.render(); // 返回输出
177176

178177
**`removeChild and removeChildFromContainer`**
179178

180-
当我们在一个被移除的宿主组件中时,现在可以从树中移除节点。如果返回的 Fiber 是容器,那么我们使用 `removeChildFromContainer` 从容器中删除节点,否则我们使用 `removeChild`
179+
从树中移除节点。如果返回的 Fiber 是容器,那么我们使用 `removeChildFromContainer` 从容器中删除节点,否则我们使用 `removeChild`
181180

182181
**`insertBefore`**
183182

184-
它是一个 `commitPlacement` 钩子,在所有节点递归插入父节点时调用。这被抽象为 `getHostSibling` 的函数,该函数会持续搜索树,直到找到同级宿主节点(React 可能会在下一个版本中改变这种方法,因为它不是一种高效的方法,因为它会导致指数级的搜索复杂性)
183+
在目标节点之前插入一个子节点
185184

186185
**`appendChildToContainer`**
187186

188187
如果 Fiber 的类型是 `HostRoot``HostPortal`,则将子节点添加到该容器中。
189188

190189
**`appendChild`**
191190

192-
添加子节点到父节点中
191+
向目标节点添加子节点
193192

194193
**`shouldSetTextContent`**
195194

196-
如果它返回 false,则重置文本内容
195+
如果它返回 false,重置文本内容
197196

198197
**`getHostContext`**
199198

200-
它用于标记当前的宿主上下文(根节点实例),用于发送更的内容,从而更新正在进行的 Fiber 队列(可能表示存在变化)。
199+
用于标记当前的宿主上下文(根元素实例),发送更新的内容,从而更新正在进行中的 Fiber 队列(可能表示存在变化)。
201200

202201
**`createTextInstance`**
203202

204203
创建文本节点的实例。
205204

206205
**`supportsMutation`**
207206

208-
`True` 用于 **可变渲染器**,其中宿主目标具有像 DOM 中的 `appendChild` 这样的可变 API。
207+
`true` **可变渲染器** 模式,其中宿主目标需要具有像 DOM 中的 `appendChild` 这样的可变 API。
209208

210-
### Note
209+
### 注意
211210

212-
***不应该** 依赖 Fiber 的数据结构。将其字段视为私有
213-
* 将 'internalInstanceHandle' 对象视为一个黑盒
211+
***不应该** 依赖 Fiber 的数据结构。将其属性视为私有
212+
* 将 'internalInstanceHandle' 对象视为黑盒
214213
* 使用宿主上下文方法从根节点获取数据。
215214

216215
> 在与 [Dan Abramov](https://twitter.com/dan_abramov) 讨论宿主配置方法和 Fiber 属性后,将上述要点添加到教程中。
217216
218217
## 将第三方渲染器注入开发工具中
219218

220-
你还可以将渲染器注入 react-devtools 以调试环境的宿主组件。早期,注入第三方渲染器是不可能的,但现在使用返回的 `reconciler` 实例,可以将渲染器注入 react-devtools。
219+
你还可以将渲染器注入 react-devtools 以调试你环境中的宿主组件。早期,是无法适配第三方渲染器的,但现在可以使用返回的 `reconciler` 实例,将渲染器注入到 react-devtools。
221220

222221
**使用**
223222

@@ -263,7 +262,7 @@ module.exports = CustomRenderer;
263262
const CustomRenderer = require('./reconciler')
264263

265264
function render(element, target, callback) {
266-
... // 在这里,使用 CustomRenderer.updateContainer() 进行顶层更新,有关更多详细信息,请参阅 Part-IV。
265+
... // 在这里,使用 CustomRenderer.updateContainer() 进行从最顶层开始的更新,有关更多详细信息,请参阅 Part-IV。
267266
CustomRenderer.injectIntoDevTools({
268267
bundleType: 1, // 0 for PROD, 1 for DEV
269268
version: '0.1.0', // version for your renderer
@@ -273,10 +272,10 @@ function render(element, target, callback) {
273272
}
274273
```
275274

276-
我们完成了教程的第一部分。我知道仅通过阅读代码很难理解其中的某些概念。开始的时候感觉很混沌,但是继续尝试,最终它会变得清晰。刚开始学习 Fiber 架构的时候,我什么都不懂。我感到极为沮丧,但我在上述代码的每一部分都使用了 `console.log()` 并试图理解它的实现,然后出现了“芜湖 芜湖”的时刻,它最终帮助我构建了 [redocx](https://github.com/nitin42/redocx)。它是有点难以理解,但你终将会明白
275+
我们完成了教程的第一部分。我知道其中的某些概念仅通过阅读代码是很难理解的。开始的时候感觉很混沌,但请继续尝试,最终它会逐渐变得清晰。刚开始学习 Fiber 架构的时候,我什么都不懂。我感到极为沮丧,但我在上述代码的每一部分都使用了 `console.log()` 并试图理解它们,然后出现了“芜湖起飞”的时刻,最终帮助我构建了 [redocx](https://github.com/nitin42/redocx)。它是有点难理解,但你终将会搞懂
277276

278-
如果你仍然有任何疑问,我在 Twitter 上的 [@NTulswani](https://twitter.com/NTulswani)
277+
如果你仍然有任何疑问,我在 Twitter [@NTulswani](https://twitter.com/NTulswani)
279278

280279
[更多渲染器的实际示例](https://github.com/facebook/react/tree/master/packages/react-reconciler#practical-examples)
281280

282-
[继续第二部分]](./part-two.md)
281+
[继续第二部分]](./part-two-zh_CN.md)

part-three-zh_CN.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 第三部分
22

3-
这是我们教程的最后一部分。我们已经完成了所有繁重的工作,创建了一个 React 调度器,为我们的调度器创建了一个公共接口,设计了组件 API。
3+
这是我们教程的最后一部分。我们已经完成了所有繁重的工作,创建了一个 React 调度器,为我们的调度器创建了一个公开方法,设计了组件的 API。
44

55
现在我们只需要创建一个 `render` 方法来将所有内容渲染到宿主环境中。
66

@@ -48,25 +48,25 @@ export default render;
4848

4949
**`container`**
5050

51-
这是根节点实例(还记得我们调度器中的 `rootContainerInstance` 吗?)。
51+
这是根元素实例(还记得我们调度器中的 `rootContainerInstance` 吗?)。
5252

5353
**`WordRenderer.createContainer`**
5454

5555
这个方法接受一个 `root` 容器并返回当前的 Fiber(已完成的 Fiber)。记住 Fiber 是一个包含相关组件输入和输出信息的 JavaScript 对象。
5656

5757
**`WordRenderer.updateContainer`**
5858

59-
这个函数接收元素、根容器、父组件、回调函数并执行一次顶层更新
60-
这是根据当前 Fiber 和优先级(取决于上下文)调度更新来实现的
59+
这个函数接收元素、根容器、父组件、回调函数并触发一次从最顶层开始的更新
60+
这是根据当前 Fiber 和优先级(取决于上下文)来调度更新实现的
6161

6262
最后,我们渲染所有子节点并通过创建写入流来生成 word 文档。
6363

6464
仍有疑惑?查看 [常见问题](./faq.md)
6565

66-
恭喜!你已成功完成本教程。本教程的完整源代码已在此代码库 ([src](./src)) 中提供。如果你想阅读整个源代码,请按照以下顺序 -
66+
恭喜!你已成功完成本教程。本教程的完整源代码在此代码库 ([src](./src)) 中提供。如果你想阅读整个源代码,请按照以下顺序 -
6767

6868
[`reconciler`](./src/reconciler/index.js) => [`components`](./src/components/) => [`createElement`](./src/utils/createElement.js) => [`render method`](./src/render/index.js)
6969

70-
如果你喜欢阅读本教程,请 watch 或 star 这个代码库,并在 [Twitter](http://twitter.com/NTulswani) 上关注我以获取更新
70+
如果你喜欢阅读本教程,请 watch 或 star 这个代码库,并在 [Twitter](http://twitter.com/NTulswani) 上关注我以获取最新的消息
7171

7272
感谢你阅读本教程!

0 commit comments

Comments
 (0)