diff --git a/content/docs/implementation-notes.md b/content/docs/implementation-notes.md
index b345f7d5d..193c5f192 100644
--- a/content/docs/implementation-notes.md
+++ b/content/docs/implementation-notes.md
@@ -9,93 +9,93 @@ redirect_from:
- "contributing/implementation-notes.html"
---
-This section is a collection of implementation notes for the [stack reconciler](/docs/codebase-overview.html#stack-reconciler).
+Bài viết này bao gồm các ghi chú về việc thực thi [stack reconciler](/docs/codebase-overview.html#stack-reconciler).
-It is very technical and assumes a strong understanding of React public API as well as how it's divided into core, renderers, and the reconciler. If you're not very familiar with the React codebase, read [the codebase overview](/docs/codebase-overview.html) first.
+Bài viết đòi hỏi kiến thức chuyên môn cao và sự thông hiểu tốt về các public API của React cũng như cách nó được phân ra các phần cốt lõi (core), các phần render (renderer) và phần điều phối, cập nhật component (reconciler). Nếu bạn chưa nắm rõ về codebase của React, trước tiên hãy đọc [tổng quan codebase](/docs/codebase-overview.html).
-It also assumes an understanding of the [differences between React components, their instances, and elements](/blog/2015/12/18/react-components-elements-and-instances.html).
+Bạn cũng cần hiểu về [sự khác biệt giữa React components, các instance và phần tử (element) của chúng](/blog/2015/12/18/react-components-elements-and-instances.html) trước khi bước vào bài viết này.
-The stack reconciler was used in React 15 and earlier. It is located at [src/renderers/shared/stack/reconciler](https://github.com/facebook/react/tree/15-stable/src/renderers/shared/stack/reconciler).
+Stack reconciler đã được sử dụng trong React 15 và các phiên bản trước đó. Hiện thực của nó nằm ở [src/renderers/shared/stack/reconciler](https://github.com/facebook/react/tree/15-stable/src/renderers/shared/stack/reconciler).
-### Video: Building React from Scratch {#video-building-react-from-scratch}
+### Video: Xây dựng React từ con số không {#video-building-react-from-scratch}
-[Paul O'Shannessy](https://twitter.com/zpao) gave a talk about [building React from scratch](https://www.youtube.com/watch?v=_MAD4Oly9yg) that largely inspired this document.
+[Paul O'Shannessy](https://twitter.com/zpao) đã có một bài nói về việc [xây dựng React từ con số không](https://www.youtube.com/watch?v=_MAD4Oly9yg). Bài nói đó đã giúp ích rất nhiều cho bài viết này.
-Both this document and his talk are simplifications of the real codebase so you might get a better understanding by getting familiar with both of them.
+Cả bài nói và bài viết là cách trình bày đơn giản hóa cho codebase thật sự của React, nên bạn có thể hiểu rõ hơn về codebase nếu đi qua cả hai.
-### Overview {#overview}
+### Tổng quan {#overview}
-The reconciler itself doesn't have a public API. [Renderers](/docs/codebase-overview.html#renderers) like React DOM and React Native use it to efficiently update the user interface according to the React components written by the user.
+Bản thân reconciler không có API mở (public API). [Các phần render](/docs/codebase-overview.html#renderers) như React DOM và React Native sử dụng nó để cập nhật giao diện người dùng một cách hiệu quả theo những component mà người dùng viết.
-### Mounting as a Recursive Process {#mounting-as-a-recursive-process}
+### Quá trình mounting đệ quy {#mounting-as-a-recursive-process}
-Let's consider the first time you mount a component:
+Hãy nhìn lại lần đầu tiên chúng ta mount một component:
```js
ReactDOM.render(, rootEl);
```
-React DOM will pass `` along to the reconciler. Remember that `` is a React element, that is, a description of *what* to render. You can think about it as a plain object:
+React DOM sẽ đưa `` đến reconciler. Hãy nhớ rằng `` là một phần tử của React, nghĩa là, nó miêu tả *cái gì* được render. Bạn có thể xem nó như là một object thuần:
```js
console.log();
// { type: App, props: {} }
```
-The reconciler will check if `App` is a class or a function.
+Reconciler sẽ kiểm tra xem `App` là một lớp hay một hàm.
-If `App` is a function, the reconciler will call `App(props)` to get the rendered element.
+Nếu `App` là một hàm, reconciler sẽ gọi đến `App(props)` để lấy ra những phần tử được render.
-If `App` is a class, the reconciler will instantiate an `App` with `new App(props)`, call the `componentWillMount()` lifecycle method, and then will call the `render()` method to get the rendered element.
+Nếu `App` là một lớp, reconciler sẽ tạo ra một thực thể mới từ `App` với `new App(props)`, gọi đến hàm lifecycle `componentWillMount()`, và rồi gọi đến hàm `render()` để lấy ra những phần tử được render.
-Either way, the reconciler will learn the element `App` "rendered to".
+Theo hướng nào đi nữa, reconciler đều sẽ xem `App` sẽ render ra những phần tử gì.
-This process is recursive. `App` may render to a ``, `Greeting` may render to a ``, and so on. The reconciler will "drill down" through user-defined components recursively as it learns what each component renders to.
+Quá trình này là đệ quy - được lặp đi lặp lại. `App` có thể render ra ``, `Greeting` render ra ``, và cứ thế tiếp tục. Theo cách này, reconciler sẽ "đào sâu" vào những component được viết bởi người dùng để xem những component đó render ra những gì.
-You can imagine this process as a pseudocode:
+Bạn có thể tưởng tượng rõ hơn về quá trình này thông qua đoạn mã giả bên dưới:
```js
function isClass(type) {
- // React.Component subclasses have this flag
+ // Các lớp con của React.Component thì có thuộc tính this.
return (
Boolean(type.prototype) &&
Boolean(type.prototype.isReactComponent)
);
}
-// This function takes a React element (e.g. )
-// and returns a DOM or Native node representing the mounted tree.
+// Hàm này nhận vào một phần tử của React (ví dụ như )
+// và trả về một node DOM hoặc Native biểu diễn cây đã được mount.
function mount(element) {
var type = element.type;
var props = element.props;
- // We will determine the rendered element
- // by either running the type as function
- // or creating an instance and calling render().
+ // Chúng ta sẽ xác định các phần tử được render ra
+ // bằng cách dùng type làm hàm
+ // hoặc tạo ra một thực thể từ lóp và gọi hàm render().
var renderedElement;
if (isClass(type)) {
- // Component class
+ // Componenet kiểu lớp
var publicInstance = new type(props);
- // Set the props
+ // Đặt giá trị cho props
publicInstance.props = props;
- // Call the lifecycle if necessary
+ // Gọi hàm lifecycle nếu cần thiết
if (publicInstance.componentWillMount) {
publicInstance.componentWillMount();
}
- // Get the rendered element by calling render()
+ // Lấy ra những phần tử được render bằng cách gọi hàm render()
renderedElement = publicInstance.render();
} else {
- // Component function
+ // Component kiểu hàm
renderedElement = type(props);
}
- // This process is recursive because a component may
- // return an element with a type of another component.
+ // Quá trình này là đệ quy vì một component có thể trả về
+ // một phần tử của một component khác.
return mount(renderedElement);
- // Note: this implementation is incomplete and recurses infinitely!
- // It only handles elements like or .
- // It doesn't handle elements like
or yet.
+ // Ghi chú: việc thực thi này là chưa hoàn chỉnh, và còn đệ quy đến vô cùng!
+ // Nó chỉ kiểm soát các phần tử như hay .
+ // Nó chưa handle các phần tử như hay .
}
var rootEl = document.getElementById('root');
@@ -103,81 +103,81 @@ var node = mount();
rootEl.appendChild(node);
```
->**Note:**
+>**Ghi chú:**
>
->This really *is* a pseudo-code. It isn't similar to the real implementation. It will also cause a stack overflow because we haven't discussed when to stop the recursion.
+>Đây *thực sự* chỉ là một đoạn mã giả. Nó không giống với cách viết thực tế. Nó còn gây ra tràn bộ nhớ (stack overflow) vì chúng ta chưa chỉ ra khi nào sẽ kết thúc việc lặp đệ quy.
-Let's recap a few key ideas in the example above:
+Hãy chốt lại một vài ý quan trọng trong ví dụ ở trên:
-* React elements are plain objects representing the component type (e.g. `App`) and the props.
-* User-defined components (e.g. `App`) can be classes or functions but they all "render to" elements.
-* "Mounting" is a recursive process that creates a DOM or Native tree given the top-level React element (e.g. ``).
+* Các phần tử của React là các object thuần biểu diễn kiểu component (ví dụ như `App`) và các props.
+* Những component do người dùng viết (như `App`) có thể là lớp hoặc hàm, nhưng điểm chung là chúng đều chỉ ra những gì sẽ được render.
+* "Mounting" là một quá trình đệ quy, tạo ra một cây DOM hoặc Native khi được cho trước một phần tử cấp cao (như là ``).
-### Mounting Host Elements {#mounting-host-elements}
+### Mounting phần tử của hệ thống {#mounting-host-elements}
-This process would be useless if we didn't render something to the screen as a result.
+Quá trình mounting sẽ trở nên vô nghĩa nếu chúng ta không render được kết quả lên màn hình.
-In addition to user-defined ("composite") components, React elements may also represent platform-specific ("host") components. For example, `Button` might return a `` from its render method.
+Bên cạnh các component được viết bởi người dùng (còn được gọi là "composite"), React còn có các component của hệ thống (được gọi là "host"). Ví dụ, `Button` có thể trả về `` từ hàm render của nó.
-If element's `type` property is a string, we are dealing with a host element:
+Nếu thuộc tính `type` của phần tử là một chuỗi, chúng ta đang có một phần tử của hệ thống:
```js
console.log();
// { type: 'div', props: {} }
```
-There is no user-defined code associated with host elements.
+Người dùng không được viết lại hay định nghĩa lại các phần tử hệ thống.
-When the reconciler encounters a host element, it lets the renderer take care of mounting it. For example, React DOM would create a DOM node.
+Khi reconciler gặp một phần tử hệ thống, nó để cho renderer xử lí việc mounting cho phần tử đó. Ví dụ, React DOM sẽ tạo ra một node DOM.
-If the host element has children, the reconciler recursively mounts them following the same algorithm as above. It doesn't matter whether children are host (like `
`), composite (like ``), or both.
+Nếu phần tử hệ thống có các phần tử con, reconciler sẽ mount chúng một cách đệ quy theo giải thuật ở trên, không quan trọng các phần tử con là phần tử hệ thống (như `
`) hay do người dùng viết (như ``), hay là cả hai.
-The DOM nodes produced by the child components will be appended to the parent DOM node, and recursively, the complete DOM structure will be assembled.
+Các node DOM được tạo ra bởi các component con sẽ được thêm vào node DOM cha, và cứ lặp lại như vậy, cấu trúc DOM hoàn chỉnh sẽ được tạo ra.
->**Note:**
+>**Ghi chú:**
>
->The reconciler itself is not tied to the DOM. The exact result of mounting (sometimes called "mount image" in the source code) depends on the renderer, and can be a DOM node (React DOM), a string (React DOM Server), or a number representing a native view (React Native).
+>Bản thân reconciler không gắn liền với DOM. Kết quả chính xác của việc mounting (đôi lúc được gọi là "mount image" trong mã nguồn) phụ thuộc vào renderer, và có thể là một node DOM (React DOM), một chuỗi (React DOM Server), hoặc là một số để biểu diễn cách nhìn (như React Native).
-If we were to extend the code to handle host elements, it would look like this:
+Nếu chúng ta phải mở rộng code để xử lý các phần tử hệ thống, kết quả sẽ như thế này:
```js
function isClass(type) {
- // React.Component subclasses have this flag
+ // Các lớp con của React.Component thì có thuộc tính this.
return (
Boolean(type.prototype) &&
Boolean(type.prototype.isReactComponent)
);
}
-// This function only handles elements with a composite type.
-// For example, it handles and , but not a .
+// Hàm này chỉ xử lý các phần tử với kiểu composite (từ component do người dùng viết)
+// Ví dụ, nó xử lý và , nhưng không xử lý .
function mountComposite(element) {
var type = element.type;
var props = element.props;
var renderedElement;
if (isClass(type)) {
- // Component class
+ // Component kiểu lớp
var publicInstance = new type(props);
- // Set the props
+ // Đặt giá trị cho props
publicInstance.props = props;
- // Call the lifecycle if necessary
+ // Gọi hàm lifecycle nếu cần thiết
if (publicInstance.componentWillMount) {
publicInstance.componentWillMount();
}
renderedElement = publicInstance.render();
} else if (typeof type === 'function') {
- // Component function
+ // Component kiểu hàm
renderedElement = type(props);
}
- // This is recursive but we'll eventually reach the bottom of recursion when
- // the element is host (e.g. ) rather than composite (e.g. ):
+ // Đây là quá trình đệ quy nhưng quá trình lặp sẽ dừng lại
+ // khi gặp một phần tử kiểu host (ví dụ ) chứ không phải kiểu composite (e.g. ):
return mount(renderedElement);
}
-// This function only handles elements with a host type.
-// For example, it handles and but not an .
+// Hàm này chỉ xử lý các phần tử kiểu host
+// Ví dụ, nó xử lý và nhưng không xử lý .
function mountHost(element) {
var type = element.type;
var props = element.props;
@@ -187,9 +187,9 @@ function mountHost(element) {
}
children = children.filter(Boolean);
- // This block of code shouldn't be in the reconciler.
- // Different renderers might initialize nodes differently.
- // For example, React Native would create iOS or Android views.
+ // Phần code này không nên nằm trong reconciler.
+ // Các renderer khác nhau có thể khởi tạo các node khác nhau.
+ // Ví dụ, React Native sẽ tạo theo góc nhìn iOS và Android.
var node = document.createElement(type);
Object.keys(props).forEach(propName => {
if (propName !== 'children') {
@@ -197,29 +197,29 @@ function mountHost(element) {
}
});
- // Mount the children
+ // Mount phần tử con
children.forEach(childElement => {
- // Children may be host (e.g. ) or composite (e.g. ).
- // We will also mount them recursively:
+ // Kiểu của phần tử con có thể là host (như ) hoặc composite (như ).
+ // Chúng ta cũng sẽ mount các phần tử con này một cách đệ quy:
var childNode = mount(childElement);
- // This line of code is also renderer-specific.
- // It would be different depending on the renderer:
+ // Kết quả của dòng code này cũng phụ thuộc vào renderer.
+ // Kết quả khác nhau có thể được sinh ra từ các renderer khác nhau:
node.appendChild(childNode);
});
- // Return the DOM node as mount result.
- // This is where the recursion ends.
+ // Trả về node DOM là kết quả của quá trình mounting.
+ // Đây là điểm kết thúc của việc lặp đệ quy.
return node;
}
function mount(element) {
var type = element.type;
if (typeof type === 'function') {
- // User-defined components
+ // Component được viết bởi người dùng
return mountComposite(element);
} else if (typeof type === 'string') {
- // Platform-specific components
+ // Componenet của hệ thống
return mountHost(element);
}
}
@@ -229,40 +229,40 @@ var node = mount();
rootEl.appendChild(node);
```
-This is working but still far from how the reconciler is really implemented. The key missing ingredient is support for updates.
+Cách làm này vẫn dùng được nhưng còn xa so với cách reconciler thực sự được thực thi. Thiếu sót quan trọng ở đây là việc hỗ trợ cho các cập nhật và thay đổi.
-### Introducing Internal Instances {#introducing-internal-instances}
+### Giới thiệu các thực thể nội {#introducing-internal-instances}
-The key feature of React is that you can re-render everything, and it won't recreate the DOM or reset the state:
+Tính năng then chốt của React là bạn có thể render lại mọi thứ, và nó sẽ không tạo lại DOM hay đặt lại trạng thái (state):
```js
ReactDOM.render(, rootEl);
-// Should reuse the existing DOM:
+// DOM có sẵn nên được sử dụng lại:
ReactDOM.render(, rootEl);
```
-However, our implementation above only knows how to mount the initial tree. It can't perform updates on it because it doesn't store all the necessary information, such as all the `publicInstance`s, or which DOM `node`s correspond to which components.
+Tuy nhiên, cách thực thi ở trên chỉ mount cây được tạo đầu tiên. Nó không thể thực hiện việc cập nhật trên cây đó vì nó không có những thông tin cần thiết, ví dụ như các `publicInstance`, hay `node` DOM nào tương ứng với component nào.
-The stack reconciler codebase solves this by making the `mount()` function a method and putting it on a class. There are drawbacks to this approach, and we are going in the opposite direction in the [ongoing rewrite of the reconciler](/docs/codebase-overview.html#fiber-reconciler). Nevertheless this is how it works now.
+Codebase của stack reconciler giải quyết vấn đề này bằng cách biến hàm `mount` thành một phương thức và đưa nó vào trong lớp. Cách tiếp cận này có nhược điểm, và đi ngược lại so với hướng đi trong việc [viết lại reconciler](/docs/codebase-overview.html#fiber-reconciler). Tuy vậy hiện tại thì đây là cách thực thi.
-Instead of separate `mountHost` and `mountComposite` functions, we will create two classes: `DOMComponent` and `CompositeComponent`.
+Thay vì chia ra hai hàm `mountHost` và `mountComposite`, chúng ta sẽ tạo ra hai lớp: `DOMComponent` và `CompositeComponent`.
-Both classes have a constructor accepting the `element`, as well as a `mount()` method returning the mounted node. We will replace a top-level `mount()` function with a factory that instantiates the correct class:
+Cả hai lớp này có một hàm dựng (constructor) nhận phần tử (`element`) là tham số đầu vào, và một hàm `mount()` trả về node đã được mount. Chúng ta sẽ thay thế hàm cấp cao `mount()` bằng một hàm khác để khởi tạo một lớp phù hợp:
```js
function instantiateComponent(element) {
var type = element.type;
if (typeof type === 'function') {
- // User-defined components
+ // Component được viết bởi người dùng
return new CompositeComponent(element);
} else if (typeof type === 'string') {
- // Platform-specific components
+ // Component hệ thống
return new DOMComponent(element);
}
}
```
-First, let's consider the implementation of `CompositeComponent`:
+Đầu tiên, hãy xem cách hiện thực của `CompositeComponent`:
```js
class CompositeComponent {
@@ -273,7 +273,7 @@ class CompositeComponent {
}
getPublicInstance() {
- // For composite components, expose the class instance.
+ // Đối với component được viết bởi người dùng, ta trả về thực thể (instance) của lớp.
return this.publicInstance;
}
@@ -285,45 +285,45 @@ class CompositeComponent {
var publicInstance;
var renderedElement;
if (isClass(type)) {
- // Component class
+ // Component kiểu lớp
publicInstance = new type(props);
- // Set the props
+ // Đặt giá trị cho props
publicInstance.props = props;
- // Call the lifecycle if necessary
+ // Gọi hàm lifecycle nếu cần
if (publicInstance.componentWillMount) {
publicInstance.componentWillMount();
}
renderedElement = publicInstance.render();
} else if (typeof type === 'function') {
- // Component function
+ // Component kiểu hàm
publicInstance = null;
renderedElement = type(props);
}
- // Save the public instance
+ // Lưu lại publicInstance
this.publicInstance = publicInstance;
- // Instantiate the child internal instance according to the element.
- // It would be a DOMComponent for or ,
- // and a CompositeComponent for or :
+ // Khởi tạo thực thể con bên trong tương ứng với element.
+ // Đó có thể là một component hệ thống như hay ,
+ // hoặc một component được viết bởi người dùng như hay :
var renderedComponent = instantiateComponent(renderedElement);
this.renderedComponent = renderedComponent;
- // Mount the rendered output
+ // Mount kết quả được render
return renderedComponent.mount();
}
}
```
-This is not much different from our previous `mountComposite()` implementation, but now we can save some information, such as `this.currentElement`, `this.renderedComponent`, and `this.publicInstance`, for use during updates.
+Không khác nhiều so với cách hiện thực trước đó của hàm `mountComposite()`, nhưng cách này cho chúng ta có thể lưu trữ thông tin, ví dụ như `this.currentElement`, `this.renderedComponent`, và `this.publicInstance`, để sử dụng trong quá trình cập nhật.
-Note that an instance of `CompositeComponent` is not the same thing as an instance of the user-supplied `element.type`. `CompositeComponent` is an implementation detail of our reconciler, and is never exposed to the user. The user-defined class is the one we read from `element.type`, and `CompositeComponent` creates an instance of it.
+Hãy nhớ rằng một thực thể tạo ra từ `CompositeComponent` không giống với một thực thể người dùng tạo ra có kiểu `element.type`. `CompositeComponent` là chi tiết về cách hiện thực của reconciler, và sẽ không bao giờ được đưa ra cho phía người dùng. Các lớp do người dùng định nghĩa có kiểu `element.type`, và `CompositeComponent` sẽ tạo ra một thực thể của nó
-To avoid the confusion, we will call instances of `CompositeComponent` and `DOMComponent` "internal instances". They exist so we can associate some long-lived data with them. Only the renderer and the reconciler are aware that they exist.
+Để tránh sự rắc rối này, chúng ta gọi các thực thể từ `CompositeComponent` và `DOMComponent` là các "thực thể nội" (internal instances). Việc này cho phép chúng ta sử dụng những dữ liệu mang tính lâu dài ở trong các thành phần này. Chỉ có renderer và reconciler mới cần quan tâm đến sự hiện diện của các thực thể này.
-In contrast, we call an instance of the user-defined class a "public instance". The public instance is what you see as `this` in the `render()` and other methods of your custom components.
+Ngược lại, với các lớp do người dùng định nghĩa, các thực thể tạo ra từ đó sẽ được gọi là các "thực thể chung" (public instance). Thực thể chung là những gì chúng ta thấy ở thuộc tính `this` của `render()` và những phương thức khác của component của bạn viết.
-The `mountHost()` function, refactored to be a `mount()` method on `DOMComponent` class, also looks familiar:
+Hàm `mountHost()`, được cấu trúc lại thành phương thức `mount()` trong `DOMComponent`, cũng được hiện thực tương tự:
```js
class DOMComponent {
@@ -334,7 +334,7 @@ class DOMComponent {
}
getPublicInstance() {
- // For DOM components, only expose the DOM node.
+ // Đối với các component của DOM, ta chỉ trả về các node DOM.
return this.node;
}
@@ -347,36 +347,36 @@ class DOMComponent {
children = [children];
}
- // Create and save the node
+ // Khởi tạo node mới và lưu lại
var node = document.createElement(type);
this.node = node;
- // Set the attributes
+ // Gán giá trị cho các thuộc tính
Object.keys(props).forEach(propName => {
if (propName !== 'children') {
node.setAttribute(propName, props[propName]);
}
});
- // Create and save the contained children.
- // Each of them can be a DOMComponent or a CompositeComponent,
- // depending on whether the element type is a string or a function.
+ // Khởi tạo và lưu lại những thành phần con được chứa bên trong.
+ // Mỗi thành phần có thể là DOMComponent hoặc CompositeComponent,
+ // phụ thuộc vào kiểu của element là chuỗi hay hàm.
var renderedChildren = children.map(instantiateComponent);
this.renderedChildren = renderedChildren;
- // Collect DOM nodes they return on mount
+ // Lưu lại những node DOM được trả về từ quá trình mounting
var childNodes = renderedChildren.map(child => child.mount());
childNodes.forEach(childNode => node.appendChild(childNode));
- // Return the DOM node as mount result
+ // Trả về node DOM là kết quả của quá trình mounting
return node;
}
}
```
-The main difference after refactoring from `mountHost()` is that we now keep `this.node` and `this.renderedChildren` associated with the internal DOM component instance. We will also use them for applying non-destructive updates in the future.
+Khác biệt chính sau khi cấu trúc lại `mountHost()` là bây giờ chúng ta lưu các thuộc tính `this.node` và `this.renderedChildren` cùng với các thực thể nội của DOM component. Sau này, chúng ta sẽ sử dụng chúng để hiện thực việc cập nhật mà không cần phải xây dựng lại cây DOM từ đầu.
-As a result, each internal instance, composite or host, now points to its child internal instances. To help visualize this, if a function `` component renders a `