Skip to content

Commit

Permalink
Merge pull request #2 from discountry/master
Browse files Browse the repository at this point in the history
update
  • Loading branch information
TigerWFH committed May 27, 2017
2 parents daf2a28 + b12f3f1 commit 1a6d56a
Show file tree
Hide file tree
Showing 9 changed files with 434 additions and 420 deletions.
42 changes: 21 additions & 21 deletions docs/_data/nav_tutorial.yml
@@ -1,88 +1,88 @@
- title: Tutorial
- title: 入门教程
items:
- id: tutorial
title: Before We Start
title: 课前准备
subitems:
- id: what-were-building
title: What We're Building
title: 教程简介
href: /react/tutorial/tutorial.html#what-were-building
forceInternal: true
- id: prerequisites
title: Prerequisites
title: 前置知识
href: /react/tutorial/tutorial.html#prerequisites
forceInternal: true
- id: how-to-follow-along
title: How to Follow Along
title: 如何编写代码
href: /react/tutorial/tutorial.html#how-to-follow-along
forceInternal: true
- id: help-im-stuck
title: Help, I'm Stuck!
title: 寻求帮助
href: /react/tutorial/tutorial.html#help-im-stuck
forceInternal: true
- id: overview
title: Overview
title: 总览
href: /react/tutorial/tutorial.html#overview
forceInternal: true
subitems:
- id: what-is-react
title: What is React?
title: React 是什么?
href: /react/tutorial/tutorial.html#what-is-react
forceInternal: true
- id: getting-started
title: Getting Started
title: 开始编码
href: /react/tutorial/tutorial.html#getting-started
forceInternal: true
- id: passing-data-through-props
title: Passing Data Through Props
title: 通过 Props 传递数据
href: /react/tutorial/tutorial.html#passing-data-through-props
forceInternal: true
- id: an-interactive-component
title: An Interactive Component
title: 给组件添加交互功能
href: /react/tutorial/tutorial.html#an-interactive-component
forceInternal: true
- id: developer-tools
title: Developer Tools
title: 开发工具
href: /react/tutorial/tutorial.html#developer-tools
forceInternal: true
- id: lifting-state-up
title: Lifting State Up
title: 状态提升
href: /react/tutorial/tutorial.html#lifting-state-up
forceInternal: true
subitems:
- id: why-immutability-is-important
title: Why Immutability Is Important
title: 为什么不可变性在React当中非常重要
href: /react/tutorial/tutorial.html#why-immutability-is-important
forceInternal: true
- id: functional-components
title: Functional Components
title: 函数定义组件
href: /react/tutorial/tutorial.html#functional-components
forceInternal: true
- id: taking-turns
title: Taking Turns
title: 轮流落子
href: /react/tutorial/tutorial.html#taking-turns
forceInternal: true
- id: declaring-a-winner
title: Declaring a Winner
title: 判断赢家
href: /react/tutorial/tutorial.html#declaring-a-winner
forceInternal: true
- id: storing-a-history
title: Storing A History
title: 保存历史纪录
href: /react/tutorial/tutorial.html#storing-a-history
forceInternal: true
subitems:
- id: showing-the-moves
title: Showing the Moves
title: 展示每步历史纪录链接
href: /react/tutorial/tutorial.html#showing-the-moves
forceInternal: true
- id: keys
title: Keys
href: /react/tutorial/tutorial.html#keys
forceInternal: true
- id: implementing-time-travel
title: Implementing Time Travel
title: 实现时间旅行
href: /react/tutorial/tutorial.html#implementing-time-travel
forceInternal: true
- id: wrapping-up
title: Wrapping Up
title: 总结
href: /react/tutorial/tutorial.html#wrapping-up
forceInternal: true
4 changes: 2 additions & 2 deletions docs/_layouts/tutorial.html
Expand Up @@ -8,8 +8,8 @@

<div class="inner-content">
<a class="edit-page-link"
href="https://github.com/facebook/react/tree/master/docs/{{ page.path }}"
target="_blank">Edit on GitHub</a>
href="https://github.com/discountry/react/tree/master/docs/{{ page.path }}"
target="_blank">纠错</a>
<h1>
{{ page.title }}
</h1>
Expand Down
129 changes: 65 additions & 64 deletions docs/docs/integrating-with-other-libraries.md

Large diffs are not rendered by default.

84 changes: 42 additions & 42 deletions docs/docs/reconciliation.md
@@ -1,35 +1,35 @@
---
id: reconciliation
title: Reconciliation
title: 协调(Reconciliation
permalink: docs/reconciliation.html
---

React provides a declarative API so that you don't have to worry about exactly what changes on every update. This makes writing applications a lot easier, but it might not be obvious how this is implemented within React. This article explains the choices we made in React's "diffing" algorithm so that component updates are predictable while being fast enough for high-performance apps.
React提供了一组声明式API以让你不必关心每次更新的变化。这使得应用的编写容易了很多,但在React中如何实现并不是很清晰。这篇文章解释了React对比算法的选择以让组件更新可预测并使得高性能应用足够快。

## Motivation
## 目的

When you use React, at a single point in time you can think of the `render()` function as creating a tree of React elements. On the next state or props update, that `render()` function will return a different tree of React elements. React then needs to figure out how to efficiently update the UI to match the most recent tree.
当你使用React,在单一时间点你可以考虑`render()`函数作为创建React元素的树。在下一次状态或属性更新,`render()`函数将返回一个不同的React元素的树。React需要算出如何高效更新UI以匹配最为接近的树。

There are some generic solutions to this algorithmic problem of generating the minimum number of operations to transform one tree into another. However, the [state of the art algorithms](http://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf) have a complexity in the order of O(n<sup>3</sup>) where n is the number of elements in the tree.
有一些解决将一棵树转换为另一棵树的最小操作数算法问题的通用方案。然而,树中元素个数为n,[最先进的算法](http://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf) 的时间复杂度为O(n<sup>3</sup>)

If we used this in React, displaying 1000 elements would require in the order of one billion comparisons. This is far too expensive. Instead, React implements a heuristic O(n) algorithm based on two assumptions:
若我们在React中使用,展示1000个元素则需要进行10亿次的比较。这操作太过昂贵,相反,React基于两点假设,实现了一个启发的O(n)算法:

1. Two elements of different types will produce different trees.
2. The developer can hint at which child elements may be stable across different renders with a `key` prop.
1. 两个不同类型的元素将产生不同的树。
2. 通过渲染器附带`key`属性,开发者可以示意哪些子元素可能是稳定的。

In practice, these assumptions are valid for almost all practical use cases.
实践中,上述假设适用于大部分应用场景。

## The Diffing Algorithm
## 对比算法

When diffing two trees, React first compares the two root elements. The behavior is different depending on the types of the root elements.
当对比两棵树时,React首先比较两个根节点。根据不同类型的根元素,其行为也不同。

### Elements Of Different Types
### 元素的不同类型

Whenever the root elements have different types, React will tear down the old tree and build the new tree from scratch. Going from `<a>` to `<img>`, or from `<Article>` to `<Comment>`, or from `<Button>` to `<div>` - any of those will lead to a full rebuild.
每当根元素有不同类型,React将卸载旧树并重新构建新树。从`<a>``<img>`或从`<Article>``<Comment>`,或从`<Button>` `<div>`,任何的调整都会导致全部重建。

When tearing down a tree, old DOM nodes are destroyed. Component instances receive `componentWillUnmount()`. When building up a new tree, new DOM nodes are inserted into the DOM. Component instances receive `componentWillMount()` and then `componentDidMount()`. Any state associated with the old tree is lost.
当树被卸载,旧的DOM节点将被销毁。组件实例将会接收到`componentWillUnmount()`方法。当构建一棵新树,新的DOM节点被插入到DOM中。组件实例将接收到`componentWillMount()`以及之后的`componentDidMount()`。任何有关旧树的状态都将被丢弃。

Any components below the root will also get unmounted and have their state destroyed. For example, when diffing:
下面任何组件的根节点将会被卸载同时他们的状态将销毁。例如,在进行对比:

```xml
<div>
Expand All @@ -41,43 +41,43 @@ Any components below the root will also get unmounted and have their state destr
</span>
```

This will destroy the old `Counter` and remount a new one.
这将会销毁旧的`Counter`并重装新节点。

### DOM Elements Of The Same Type
### 相同类型的DOM元素

When comparing two React DOM elements of the same type, React looks at the attributes of both, keeps the same underlying DOM node, and only updates the changed attributes. For example:
当比较两个相同类型的React DOM元素时,React则会观察二者的属性,保持相同的底层DOM节点,并仅更新变化的属性。例如:

```xml
<div className="before" title="stuff" />

<div className="after" title="stuff" />
```

By comparing these two elements, React knows to only modify the `className` on the underlying DOM node.
通过比较两个元素,React知道仅更改底层DOM元素的`className`

When updating `style`, React also knows to update only the properties that changed. For example:
当更新`style`时,React同样知道仅更新变更的属性。例如:

```xml
<div style={{'{{'}}color: 'red', fontWeight: 'bold'}} />

<div style={{'{{'}}color: 'green', fontWeight: 'bold'}} />
```

When converting between these two elements, React knows to only modify the `color` style, not the `fontWeight`.
当在调整两个元素时,React知道仅改变`color`样式而不是`fontWeight`

After handling the DOM node, React then recurses on the children.
在处理完DOM元素后,React递归其子元素。

### Component Elements Of The Same Type
### 相同类型的组件元素

When a component updates, the instance stays the same, so that state is maintained across renders. React updates the props of the underlying component instance to match the new element, and calls `componentWillReceiveProps()` and `componentWillUpdate()` on the underlying instance.
当组件更新时,实例仍保持一致,以让状态能够在渲染之间保留。React更新底层组件实例的属性以满足新元素,并在底层实例上调用`componentWillReceiveProps()` `componentWillUpdate()` 方法。

Next, the `render()` method is called and the diff algorithm recurses on the previous result and the new result.
接下来,`render()`方法被调用,同时对比算法会递归处理之前的结果和新的结果。

### Recursing On Children
### 递归子节点

By default, when recursing on the children of a DOM node, React just iterates over both lists of children at the same time and generates a mutation whenever there's a difference.
默认时。当递归DOM节点的子节点,React仅在同一时间点递归两个子节点列表,并在有不同时产生一个变更。

For example, when adding an element at the end of the children, converting between these two trees works well:
例如,当在子节点末尾增加一个元素,两棵树的转换效果很好:

```xml
<ul>
Expand All @@ -92,9 +92,9 @@ For example, when adding an element at the end of the children, converting betwe
</ul>
```

React will match the two `<li>first</li>` trees, match the two `<li>second</li>` trees, and then insert the `<li>third</li>` tree.
React将会匹配两棵树的`<li>first</li>`,并匹配两棵树的`<li>second</li>` 节点,并插入`<li>third</li>`节点树。

If you implement it naively, inserting an element at the beginning has worse performance. For example, converting between these two trees works poorly:
若原生实现,在开始插入元素会使得性能更棘手。例如,两棵树的转换效果则比较糟糕:

```xml
<ul>
Expand All @@ -109,11 +109,11 @@ If you implement it naively, inserting an element at the beginning has worse per
</ul>
```

React will mutate every child instead of realizing it can keep the `<li>Duke</li>` and `<li>Villanova</li>` subtrees intact. This inefficiency can be a problem.
React会调整每个子节点,而非意识到可以完整保留`<li>Duke</li>` `<li>Villanova</li>`子树。低效成了一个问题。

### Keys

In order to solve this issue, React supports a `key` attribute. When children have keys, React uses the key to match children in the original tree with children in the subsequent tree. For example, adding a `key` to our inefficient example above can make the tree conversion efficient:
为解决该问题,React支持了一个`key`属性。当子节点有key时,React使用key来匹配原本树的子节点和新树的子节点。例如,增加一个`key`在之前效率不高的样例中能让树的转换变得高效:

```xml
<ul>
Expand All @@ -128,26 +128,26 @@ In order to solve this issue, React supports a `key` attribute. When children ha
</ul>
```

Now React knows that the element with key `'2014'` is the new one, and the elements with the keys `'2015'` and `'2016'` have just moved.
现在React知道带有`'2014'`的key的元素是新的,并仅移动带有`'2015'``'2016'`的key的元素。

In practice, finding a key is usually not hard. The element you are going to display may already have a unique ID, so the key can just come from your data:
实践中,发现key通常不难。你将展示的元素可能已经带有一个唯一的ID,因此key可以来自于你的数据中:

```js
<li key={item.id}>{item.name}</li>
```

When that's not the case, you can add a new ID property to your model or hash some parts of the content to generate a key. The key only has to be unique among its siblings, not globally unique.
当这已不再是问题,你可以增加一个新的ID属性到数据层或内容的部分哈希值以生成key。key必须在其兄弟节点中是唯一的,而非全局唯一。

As a last resort, you can pass item's index in the array as a key. This can work well if the items are never reordered, but reorders will be slow.
万不得已,你可以传递他们在数组中的索引作为key。若元素没有重排,该方法效果不错,但重排会使得其变慢。

## Tradeoffs
## 权衡

It is important to remember that the reconciliation algorithm is an implementation detail. React could rerender the whole app on every action; the end result would be the same. We are regularly refining the heuristics in order to make common use cases faster.
牢记协调算法的实现细节非常中。React可能会在每次操作时渲染整个应用;而结果仍是相同的。为保证大多数场景效率能更快,我们通常提炼启发式的算法。

In the current implementation, you can express the fact that a subtree has been moved amongst its siblings, but you cannot tell that it has moved somewhere else. The algorithm will rerender that full subtree.
在目前实现中,可以表明一个事实,即子树在其兄弟节点中移动,但你无法告知其移动到哪。该算法会重渲整个子树。

Because React relies on heuristics, if the assumptions behind them are not met, performance will suffer.
由于React依赖于该启发式算法,若其背后的假设没得到满足,则其性能将会受到影响:

1. The algorithm will not try to match subtrees of different component types. If you see yourself alternating between two component types with very similar output, you may want to make it the same type. In practice, we haven't found this to be an issue.
1. 算法无法尝试匹配不同组件类型的子元素。若你发现两个输出非常相似的组件类型交替出现,你可能希望使其成为相同类型。实践中,我们并非发现这是一个问题。

2. Keys should be stable, predictable, and unique. Unstable keys (like those produced by `Math.random()`) will cause many component instances and DOM nodes to be unnecessarily recreated, which can cause performance degradation and lost state in child components.
2. Keys应该是稳定的,可预测的,且唯一的。不稳定的key(类似由`Math.random()`生成的)将使得大量组件实例和DOM节点进行不必要的重建,使得性能下降并丢失子组件的状态。

0 comments on commit 1a6d56a

Please sign in to comment.