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

doc(cn) - translate form #95

Merged
merged 10 commits into from
Mar 7, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
124 changes: 63 additions & 61 deletions content/docs/forms.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
id: forms
title: Forms
title: 表单
permalink: docs/forms.html
prev: lists-and-keys.html
next: lifting-state-up.html
Expand All @@ -9,27 +9,27 @@ redirect_from:
- "docs/forms-zh-CN.html"
---

QC-L marked this conversation as resolved.
Show resolved Hide resolved
HTML form elements work a little bit differently from other DOM elements in React, because form elements naturally keep some internal state. For example, this form in plain HTML accepts a single name:
在 React 里,HTML 表单元素的工作方式和其他的 DOM 元素有些不同,这是因为表单元素通常会保持一些内部的 state。例如这个纯 HTML 表单只接受一个名称:

```html
<form>
<label>
Name:
名字:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
<input type="submit" value="提交" />
</form>
```

This form has the default HTML form behavior of browsing to a new page when the user submits the form. If you want this behavior in React, it just works. But in most cases, it's convenient to have a JavaScript function that handles the submission of the form and has access to the data that the user entered into the form. The standard way to achieve this is with a technique called "controlled components".
此表单具有默认的 HTML 表单行为,即在用户提交表单后浏览到新页面。如果你在 React 中执行相同的代码,它依然有效。但大多数情况下,使用 JavaScript 函数可以很方便的处理表单的提交, 同时还可以访问用户填写的表单数据。实现这种效果的标准方式是使用“受控组件”。

## Controlled Components {#controlled-components}
## 受控组件 {#controlled-components}

In HTML, form elements such as `<input>`, `<textarea>`, and `<select>` typically maintain their own state and update it based on user input. In React, mutable state is typically kept in the state property of components, and only updated with [`setState()`](/docs/react-component.html#setstate).
HTML 中,表单元素(如`<input>` `<textarea>` `<select>`)之类的表单元素通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 [`setState()`](/docs/react-component.html#setstate)来更新。

We can combine the two by making the React state be the "single source of truth". Then the React component that renders a form also controls what happens in that form on subsequent user input. An input form element whose value is controlled by React in this way is called a "controlled component".
我们可以把两者结合起来,使 React state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。

For example, if we want to make the previous example log the name when it is submitted, we can write the form as a controlled component:
例如,如果我们想让前一个示例在提交时打印出名称,我们可以将表单写为受控组件:

```javascript{4,10-12,24}
class NameForm extends React.Component {
Expand All @@ -46,54 +46,54 @@ class NameForm extends React.Component {
}

handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
alert('提交的名字: ' + this.state.value);
event.preventDefault();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
名字:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
<input type="submit" value="提交" />
</form>
);
}
}
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/VmmPgp?editors=0010)
[**CodePen 上尝试**](https://codepen.io/gaearon/pen/VmmPgp?editors=0010)

Since the `value` attribute is set on our form element, the displayed value will always be `this.state.value`, making the React state the source of truth. Since `handleChange` runs on every keystroke to update the React state, the displayed value will update as the user types.
由于在表单元素上设置了 `value` 属性,因此显示的值将始终为 `this.state.value`,这使得 React state 成为唯一数据源。由于 `handlechange` 在每次按键时都会执行并更新 React 的 state,因此显示的值将随着用户输入而更新。

With a controlled component, every state mutation will have an associated handler function. This makes it straightforward to modify or validate user input. For example, if we wanted to enforce that names are written with all uppercase letters, we could write `handleChange` as:
对于受控组件来说,每个 state 突变都有一个相关的处理函数。这使得修改或验证用户输入变得简单。例如,如果我们要强制要求所有名称都用大写字母书写,我们可以将 `handlechange` 改写为:

```javascript{2}
handleChange(event) {
this.setState({value: event.target.value.toUpperCase()});
}
```

## The textarea Tag {#the-textarea-tag}
## textarea 标签 {#the-textarea-tag}

In HTML, a `<textarea>` element defines its text by its children:
HTML 中, `<textarea>` 元素通过其子元素定义其文本:

```html
<textarea>
Hello there, this is some text in a text area
你好, 这是在 text area 里的文本
</textarea>
```

In React, a `<textarea>` uses a `value` attribute instead. This way, a form using a `<textarea>` can be written very similarly to a form that uses a single-line input:
而在 React 中,`<textarea>` 使用 `value` 属性代替。这样,可以使得使用 `<textarea>` 的表单和使用单行 input 的表单非常类似:

```javascript{4-6,12-14,26}
class EssayForm extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 'Please write an essay about your favorite DOM element.'
value: '请撰写一篇关于你喜欢的 DOM 元素的文章.'
};

this.handleChange = this.handleChange.bind(this);
Expand All @@ -105,40 +105,40 @@ class EssayForm extends React.Component {
}

handleSubmit(event) {
alert('An essay was submitted: ' + this.state.value);
alert('提交的文章: ' + this.state.value);
event.preventDefault();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Essay:
文章:
<textarea value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
<input type="submit" value="提交" />
</form>
);
}
}
```

Notice that `this.state.value` is initialized in the constructor, so that the text area starts off with some text in it.
请注意,`this.state.value` 初始化于构造函数中,因此文本区域默认有初值。

## The select Tag {#the-select-tag}
## select 标签 {#the-select-tag}

In HTML, `<select>` creates a drop-down list. For example, this HTML creates a drop-down list of flavors:
HTML 中,`<select>` 创建下拉列表标签。例如,如下 HTML 创建了水果相关的下拉列表:

```html
<select>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码中的内容未翻译,因为你将 Coconut 翻译为了椰子,大家读文章会很蒙

<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option selected value="coconut">Coconut</option>
<option value="mango">Mango</option>
<option value="grapefruit">葡萄柚</option>
<option value="lime">柠檬</option>
<option selected value="coconut">椰子</option>
<option value="mango">芒果</option>
</select>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码中内容是否要统一翻译?我记得之前有 PR 针对其中内容是进行翻译的。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zhangxd6 代码块中的英文也翻译一下,辛苦

```

Note that the Coconut option is initially selected, because of the `selected` attribute. React, instead of using this `selected` attribute, uses a `value` attribute on the root `select` tag. This is more convenient in a controlled component because you only need to update it in one place. For example:
请注意,由于 `selected` 属性的缘故,椰子选项默认被选中。React 并不会使用 `selected` 属性,而是在根 `select` 标签上使用 `value` 属性。这在受控组件中更便捷,因为您只需要在根标签中更新它。例如:

```javascript{4,10-12,24}
class FlavorForm extends React.Component {
Expand All @@ -155,56 +155,56 @@ class FlavorForm extends React.Component {
}

handleSubmit(event) {
alert('Your favorite flavor is: ' + this.state.value);
alert('你喜欢的风味是: ' + this.state.value);
event.preventDefault();
}

render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Pick your favorite flavor:
选择你喜欢的风味:
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
<option value="grapefruit">葡萄柚</option>
<option value="lime">柠檬</option>
<option value="coconut">椰子</option>
<option value="mango">芒果</option>
</select>
</label>
<input type="submit" value="Submit" />
<input type="submit" value="提交" />
</form>
);
}
}
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/JbbEzX?editors=0010)
[**CodePen 上尝试**](https://codepen.io/gaearon/pen/JbbEzX?editors=0010)

Overall, this makes it so that `<input type="text">`, `<textarea>`, and `<select>` all work very similarly - they all accept a `value` attribute that you can use to implement a controlled component.
总的来说,这使得 `<input type="text">`, `<textarea>` `<select>` 之类的标签都非常相似--它们都接受一个 `value` 属性,你可以使用它来实现受控组件。

> Note
> 注意
>
> You can pass an array into the `value` attribute, allowing you to select multiple options in a `select` tag:
> 你可以将数组传递到 `value` 属性中,以支持在 `select` 标签中选择多个选项:
>
>```js
><select multiple={true} value={['B', 'C']}>
>```

## The file input Tag {#the-file-input-tag}
## 文件 input 标签 {#the-file-input-tag}

In HTML, an `<input type="file">` lets the user choose one or more files from their device storage to be uploaded to a server or manipulated by JavaScript via the [File API](https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications).
HTML 中,`<input type=file>` 允许用户从存储设备中选择一个或多个文件,将其上传到服务器,或通过使用 JavaScript [File API](https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications) 进行控制。

```html
<input type="file" />
```

Because its value is read-only, it is an **uncontrolled** component in React. It is discussed together with other uncontrolled components [later in the documentation](/docs/uncontrolled-components.html#the-file-input-tag).
因为它的 value 只读,所以它是 React 中的一个**非受控**组件。将与其他非受控组件[在后续文档中](/docs/uncontrolled-components.html#the-file-input-tag)一起讨论。

## Handling Multiple Inputs {#handling-multiple-inputs}
## 处理多个输入 {#handling-multiple-inputs}

When you need to handle multiple controlled `input` elements, you can add a `name` attribute to each element and let the handler function choose what to do based on the value of `event.target.name`.
当需要处理多个 `input` 元素时,我们可以给每个元素添加 `name` 属性,并让处理函数根据 `event.target.name` 的值选择要执行的操作。

For example:
例如:

```javascript{15,18,28,37}
class Reservation extends React.Component {
Expand Down Expand Up @@ -232,7 +232,7 @@ class Reservation extends React.Component {
return (
<form>
<label>
Is going:
参与:
<input
name="isGoing"
type="checkbox"
Expand All @@ -241,7 +241,7 @@ class Reservation extends React.Component {
</label>
<br />
<label>
Number of guests:
来宾人数:
<input
name="numberOfGuests"
type="number"
Expand All @@ -254,31 +254,33 @@ class Reservation extends React.Component {
}
```

[**Try it on CodePen**](https://codepen.io/gaearon/pen/wgedvV?editors=0010)
[**CodePen 上尝试**](https://codepen.io/gaearon/pen/wgedvV?editors=0010)

Note how we used the ES6 [computed property name](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names) syntax to update the state key corresponding to the given input name:
这里使用了 ES6 [计算属性名称](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names)的语法更新给定输入名称对应的 state 值:

例如:

```js{2}
this.setState({
[name]: value
});
```

It is equivalent to this ES5 code:
等同 ES5:

```js{2}
var partialState = {};
partialState[name] = value;
this.setState(partialState);
```

Also, since `setState()` automatically [merges a partial state into the current state](/docs/state-and-lifecycle.html#state-updates-are-merged), we only needed to call it with the changed parts.
另外,由于 `setState()` 自动[将部分 state 合并到当前 state](/docs/state-and-lifecycle.html#state-updates-are-merged), 只需调用它更改部分 state 即可。

## Controlled Input Null Value {#controlled-input-null-value}
## 受控输入空值 {#controlled-input-null-value}

Specifying the value prop on a [controlled component](/docs/forms.html#controlled-components) prevents the user from changing the input unless you desire so. If you've specified a `value` but the input is still editable, you may have accidentally set `value` to `undefined` or `null`.
在[受控组件](/docs/forms.html#controlled-components)上指定 value 的 prop 可以防止用户更改输入。如果指定了 `value`,但输入仍可编辑,则可能是意外地将`value` 设置为 `undefined` `null`

The following code demonstrates this. (The input is locked at first but becomes editable after a short delay.)
下面的代码演示了这一点。(输入最初被锁定,但在短时间延迟后变为可编辑。)

```javascript
ReactDOM.render(<input value="hi" />, mountNode);
Expand All @@ -289,10 +291,10 @@ setTimeout(function() {

```

## Alternatives to Controlled Components {#alternatives-to-controlled-components}
## 受控组件的替代品 {#alternatives-to-controlled-components}

It can sometimes be tedious to use controlled components, because you need to write an event handler for every way your data can change and pipe all of the input state through a React component. This can become particularly annoying when you are converting a preexisting codebase to React, or integrating a React application with a non-React library. In these situations, you might want to check out [uncontrolled components](/docs/uncontrolled-components.html), an alternative technique for implementing input forms.
有时使用受控组件会很麻烦,因为你需要为数据变化的每种方式都编写事件处理函数,并通过一个 React 组件传递所有的输入 state。当你将之前的代码库转换为 React 或将 React 应用程序与非 React 库集成时,这可能会令人厌烦。在这些情况下,你可能希望使用[非受控组件](/docs/uncontrolled-components.html), 这是实现输入表单的另一种方式。

## Fully-Fledged Solutions {#fully-fledged-solutions}
## 成熟的解决方案 {#fully-fledged-solutions}

If you're looking for a complete solution including validation, keeping track of the visited fields, and handling form submission, [Formik](https://jaredpalmer.com/formik) is one of the popular choices. However, it is built on the same principles of controlled components and managing state — so don't neglect to learn them.
如果你想寻找包含验证、追踪访问字段以及处理表单提交的完整解决方案,使用 [Formik](https://jaredpalmer.com/formik) 是不错的选择。然而,它也是建立在受控组件和管理 state 的基础之上——所以不要忽视学习它们。
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果你正在寻找一个包含验证、已访问字段追踪以及表单提交处理的完整解决方案,Formik 是个不错的选择。不过,它也是基于受控组件和 state 管理的原理之上构建的——所以不要忽视对它们的学习。

  • 英文中很多动词的表达,翻译成名词会更符合我们的表达习惯;