Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(Advanced guides): React without ES6 #203

Merged
merged 4 commits into from
Mar 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions content/docs/react-without-es6.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
id: react-without-es6
title: React Without ES6
title: 不使用 ES6 開發 React
permalink: docs/react-without-es6.html
---

Normally you would define a React component as a plain JavaScript class:
通常你會把 React component 定義成一個 JavaScript class

```javascript
class Greeting extends React.Component {
Expand All @@ -14,7 +14,7 @@ class Greeting extends React.Component {
}
```

If you don't use ES6 yet, you may use the `create-react-class` module instead:
如果你還沒開始使用 ES6 的話,則可以考慮用 `create-react-class` 來代替:


```javascript
Expand All @@ -26,11 +26,11 @@ var Greeting = createReactClass({
});
```

The API of ES6 classes is similar to `createReactClass()` with a few exceptions.
ES6 class 與 `createReactClass()` 的 API 十分相似,只有以下幾個不同處。

## Declaring Default Props {#declaring-default-props}
## 宣告預設 Props {#declaring-default-props}

With functions and ES6 classes `defaultProps` is defined as a property on the component itself:
使用 function 與 ES6 class 語法時,`defaultProps` 會被定義為 component 上的一個屬性:

```javascript
class Greeting extends React.Component {
Expand All @@ -42,7 +42,7 @@ Greeting.defaultProps = {
};
```

With `createReactClass()`, you need to define `getDefaultProps()` as a function on the passed object:
而使用 `createReactClass()` 語法時,你則需要在傳遞的物件上定義 `getDefaultProps()` 方法:

```javascript
var Greeting = createReactClass({
Expand All @@ -57,9 +57,9 @@ var Greeting = createReactClass({
});
```

## Setting the Initial State {#setting-the-initial-state}
## 設定初始 State {#setting-the-initial-state}

In ES6 classes, you can define the initial state by assigning `this.state` in the constructor:
ES6 class 語法中,你可以藉由在 constructor 中設定 `this.state` 來定義初始 state:

```javascript
class Counter extends React.Component {
Expand All @@ -71,7 +71,7 @@ class Counter extends React.Component {
}
```

With `createReactClass()`, you have to provide a separate `getInitialState` method that returns the initial state:
而使用 `createReactClass()` 語法時,你則需要另外提供一個會回傳初始 state 的 `getInitialState` 方法:

```javascript
var Counter = createReactClass({
Expand All @@ -82,16 +82,16 @@ var Counter = createReactClass({
});
```

## Autobinding {#autobinding}
## 自動綁定 {#autobinding}

In React components declared as ES6 classes, methods follow the same semantics as regular ES6 classes. This means that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` in the constructor:
在使用 ES6 class 宣告 React component 時,其方法的語義與一般的 ES6 class 相同。也就是說,這些方法不會自動綁定 `this` instance 上。你會需要明確地在 constructor 中使用 `.bind(this)` 來綁定 `this`:

```javascript
class SayHello extends React.Component {
constructor(props) {
super(props);
this.state = {message: 'Hello!'};
// This line is important!
// 這行很重要!
this.handleClick = this.handleClick.bind(this);
}

Expand All @@ -100,7 +100,7 @@ class SayHello extends React.Component {
}

render() {
// Because `this.handleClick` is bound, we can use it as an event handler.
// 因為 `this.handleClick` 已經被綁定了,所以我們才可以把它當作 event handler 使用。
return (
<button onClick={this.handleClick}>
Say hello
Expand All @@ -110,7 +110,7 @@ class SayHello extends React.Component {
}
```

With `createReactClass()`, this is not necessary because it binds all methods:
而使用 `createReactClass()` 時就不需要這麼做,因為它會自動綁定所有方法:

```javascript
var SayHello = createReactClass({
Expand All @@ -132,9 +132,9 @@ var SayHello = createReactClass({
});
```

This means writing ES6 classes comes with a little more boilerplate code for event handlers, but the upside is slightly better performance in large applications.
這代表使用 ES6 class 時會需要為 event handler 多寫一些 boilerplate 程式碼,但這種寫法的好處是在大型的應用程式中會有稍微好一點的效能。

If the boilerplate code is too unattractive to you, you may enable the **experimental** [Class Properties](https://babeljs.io/docs/plugins/transform-class-properties/) syntax proposal with Babel:
如果寫 boilerplate 程式碼對你來說實在是很沒有吸引力的話,你可以啟用 Babel 的**實驗性**語法提案 [Class Properties](https://babeljs.io/docs/plugins/transform-class-properties/)


```javascript
Expand All @@ -143,8 +143,8 @@ class SayHello extends React.Component {
super(props);
this.state = {message: 'Hello!'};
}
// WARNING: this syntax is experimental!
// Using an arrow here binds the method:
// 警告:這個語法還在實驗階段!
// 在這裡使用 arrow function 可以綁定此方法:
handleClick = () => {
alert(this.state.message);
}
Expand All @@ -159,27 +159,27 @@ class SayHello extends React.Component {
}
```

Please note that the syntax above is **experimental** and the syntax may change, or the proposal might not make it into the language.
請注意,上述的語法還在實驗階段,也就是語法可能會改變,提案也有機會不被加入語言標準中。

If you'd rather play it safe, you have a few options:
如果你想要保險一點,你有以下幾個選擇:

* Bind methods in the constructor.
* Use arrow functions, e.g. `onClick={(e) => this.handleClick(e)}`.
* Keep using `createReactClass`.
* constructor 中綁定方法。
* 使用 arrow function,例如 `onClick={(e) => this.handleClick(e)}`
* 繼續使用 `createReactClass`

## Mixins {#mixins}
## Mixin {#mixins}

>**Note:**
> **注意:**
>
>ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes.
> ES6 並沒有支援任何 mixin 語法。因此當你在 React 中使用 ES6 class 時也不支援使用 mixin。
>
>**We also found numerous issues in codebases using mixins, [and don't recommend using them in the new code](/blog/2016/07/13/mixins-considered-harmful.html).**
> **我們也發現在程式中使用 mixin 會造成很多問題,[因此不建議在新的程式碼中使用 mixin](/blog/2016/07/13/mixins-considered-harmful.html)**
>
>This section exists only for the reference.
>此段落內容僅供參考。

Sometimes very different components may share some common functionality. These are sometimes called [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). `createReactClass` lets you use a legacy `mixins` system for that.
有時候完全不同的 component 間可能會共有相同的功能。這種狀況有時候被稱為[橫切關注點](https://en.wikipedia.org/wiki/Cross-cutting_concern) 問題。`createReactClass` 可以讓你使用舊有的 `mixins` 機制來解決此問題。

One common use case is a component wanting to update itself on a time interval. It's easy to use `setInterval()`, but it's important to cancel your interval when you don't need it anymore to save memory. React provides [lifecycle methods](/docs/react-component.html#the-component-lifecycle) that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy `setInterval()` function that will automatically get cleaned up when your component is destroyed.
一個常見的使用情境是,一個 component 想要每隔一段時間就更新自己一次。使用 `setInterval()` 就可以很容易的實現這個功能,但重要的是要在不需要 `setInterval()` 之後把它取消掉以保留記憶體空間。React 提供 [生命週期方法](/docs/react-component.html#the-component-lifecycle)讓你知道一個 component 什麼時候會被建立或銷毀。讓我們用這些方法建立一個簡易 mixin,以提供簡單的 `setInterval()` 功能,並讓這個 `setInterval()` 在你的 component 被銷毀時自動清除掉。

```javascript
var SetIntervalMixin = {
Expand All @@ -197,12 +197,12 @@ var SetIntervalMixin = {
var createReactClass = require('create-react-class');

var TickTock = createReactClass({
mixins: [SetIntervalMixin], // Use the mixin
mixins: [SetIntervalMixin], // 使用 mixin
getInitialState: function() {
return {seconds: 0};
},
componentDidMount: function() {
this.setInterval(this.tick, 1000); // Call a method on the mixin
this.setInterval(this.tick, 1000); // 呼叫一個 mixin 中的方法
},
tick: function() {
this.setState({seconds: this.state.seconds + 1});
Expand All @@ -222,4 +222,4 @@ ReactDOM.render(
);
```

If a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component.
如果一個 component 使用了複數個 mixin,且其中的多個 mixin 同時定義了相同的生命週期方法(例如,多個 mixin 都想要在 component 被銷毀時做一些清除的動作),則所有的生命週期方法都保證會被呼叫到。這些 Mixin 中的方法會依照它們的排列順序依序執行,並會在最後呼叫 component 上的對應方法。
6 changes: 3 additions & 3 deletions content/docs/react-without-jsx.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
id: react-without-jsx
title: 沒有 JSX React
title: 不使用 JSX 開發 React
permalink: docs/react-without-jsx.html
---

JSX 對於使用 React 並不是不可或缺的。當你不想在開發環境中設置編譯時,使用沒有 JSX React 格外方便。
JSX 對於使用 React 並不是不可或缺的。當你不想在開發環境中設置編譯時,不使用 JSX 開發 React 格外方便。

每個 JSX 元素都只是呼叫 `React.createElement(component, props, ...children)` 的語法糖。所有任何你能用 JSX 做的事,你都能用純 JavaScript 做到。

Expand Down Expand Up @@ -53,6 +53,6 @@ ReactDOM.render(
);
```

如果你使用這個 `React.createElement` 縮寫的格式,他可以跟沒有 JSX React 一樣方便。
如果你使用這個 `React.createElement` 縮寫的格式,他可以跟不使用 JSX 開發 React 一樣方便。

此外,你也可以參考社群專案像是 [`react-hyperscript`](https://github.com/mlmorg/react-hyperscript) 和 [`hyperscript-helpers`](https://github.com/ohanhi/hyperscript-helpers),這些專案提供了更為簡潔的語法。