From c8b137a86d30991385d5cf4cbb93c8fa06e4048b Mon Sep 17 00:00:00 2001 From: Jiacheng Dong <43509711+Jiacheng787@users.noreply.github.com> Date: Wed, 3 Nov 2021 22:25:50 +0800 Subject: [PATCH 01/13] doc(cn): responding-to-events --- beta/src/pages/learn/responding-to-events.md | 302 ++++++++++--------- 1 file changed, 152 insertions(+), 150 deletions(-) diff --git a/beta/src/pages/learn/responding-to-events.md b/beta/src/pages/learn/responding-to-events.md index 0c75cf2599..6389ce993c 100644 --- a/beta/src/pages/learn/responding-to-events.md +++ b/beta/src/pages/learn/responding-to-events.md @@ -1,24 +1,26 @@ --- -title: Responding to Events +title: 响应事件 +translators: + - Jiacheng787 --- -React lets you add event handlers to your JSX. Event handlers are your own functions that will be triggered in response to user interactions like clicking, hovering, focusing on form inputs, and so on. +React 允许你在 JSX 中添加事件处理函数。事件处理函数是你自定义的函数,它将在响应用户交互(如点击、悬停、表单输入框获得焦点等)时触发。 -* Different ways to write an event handler -* How to pass event handling logic from a parent component -* How events propagate and how to stop them +* 编写事件处理函数的不同方法 +* 如何从父组件传递事件处理逻辑 +* 事件如何传播以及如何停止它们 -## Adding event handlers +## 添加事件处理函数 {#adding-event-handlers} -To add an event handler, you will first define a function and then [pass it as a prop](/learn/passing-props-to-a-component) to the appropriate JSX tag. For example, here is a button that doesn't do anything yet: +要添加一个事件处理函数,你需要先定义一个函数,然后 [将它作为 prop 传入](/learn/passing-props-to-a-component) 合适的 JSX 标签。例如,这是一个尚未执行任何操作的按钮: @@ -26,7 +28,7 @@ To add an event handler, you will first define a function and then [pass it as a export default function Button() { return ( ); } @@ -34,23 +36,23 @@ export default function Button() { -You can make it show a message when a user clicks by following these three steps: +你可以通过以下三个步骤使它在用户点击时显示消息: -1. Declare a function called `handleClick` *inside* your `Button` component. -2. Implement the logic inside that function (use `alert` to show the message). -3. Add `onClick={handleClick}` to the ` ); } @@ -62,77 +64,77 @@ button { margin-right: 10px; } -You defined the `handleClick` function and then [passed it as a prop](/learn/passing-props-to-a-component) to ` ); } function UploadButton() { return ( - ); } @@ -207,7 +209,7 @@ function UploadButton() { export default function Toolbar() { return (
- +
); @@ -220,22 +222,22 @@ button { margin-right: 10px; } -Here, the `Toolbar` component renders a `PlayButton` and an `UploadButton`: +在这里,`Toolbar` 组件渲染了一个 `PlayButton` 组件和 `UploadButton` 组件: -- `PlayButton` passes `handlePlayClick` as the `onClick` prop to the `Button` inside. -- `UploadButton` passes `() => alert('Uploading!')` as the `onClick` prop to the `Button` inside. +- `PlayButton` 将 `handlePlayClick` 作为 `onClick` prop 传入 `Button` 组件内部。 +- `UploadButton` 将 `() => alert('正在上传!')` 作为 `onClick` prop 传入 `Button` 组件内部。 -Finally, your `Button` component accepts a prop called `onClick`. It passes that prop directly to the built-in browser ` - ); @@ -268,9 +270,9 @@ button { margin-right: 10px; } -In this example, ` ); @@ -312,17 +314,17 @@ button { margin-right: 10px; } -Notice how the `App` component does not need to know *what* `Toolbar` will do with `onPlayMovie` or `onUploadImage`. That's an implementation detail of the `Toobar`. Here, `Toolbar` passes them down as `onClick` handlers to its `Button`s, but it could later also trigger them on a keyboard shortcut. Naming props after app-specific interactions like `onPlayMovie` gives you the flexibility to change how they're used later. +请注意 `App` 组件不需要知道 `Toolbar` 将会对 `onPlayMovie` 和 `onUploadImage` 做 *什么* 。上面是一个 `Toobar` 的实现细节。在这里,`Toolbar` 将它们作为 `onClick` 处理函数向下传递给它的 `Button` ,但也可以稍后通过快捷键触发它们。用应用程序特定的交互方式(如 `onPlayMovie`)来命名 prop ,可以让你灵活地更改以后使用它们的方式。 -## Event propagation +## 事件传播 {#event-propagation} -Event handlers will also catch events from any children your component might have. We say that an event "bubbles" or "propagates" up the tree: it starts with where the event happened, and then goes up the tree. +事件处理函数还将捕获来自组件可能拥有的任何子组件的事件。我们说一个事件“冒泡”或“传播”到树的上方:它从事件发生的地方开始,然后沿着树向上传播。 -This `
` contains two buttons. Both the `
` *and* each button have their own `onClick` handlers. Which handlers do you think will fire when you click a button? +下面这个 `
` 包含两个按钮。`
` *和* 每个按钮都有自己的 `onClick` 处理函数。你认为点击按钮时会触发哪些处理函数? @@ -330,13 +332,13 @@ This `
` contains two buttons. Both the `
` *and* each button have their export default function Toolbar() { return (
{ - alert('You clicked on the toolbar!'); + alert('你点击了 toolbar !'); }}> - -
); @@ -353,19 +355,19 @@ button { margin: 5px; } -If you click on either button, its `onClick` will run first, followed by the parent `
`'s `onClick`. So two messages will appear. If you click the toolbar itself, only the parent `
`'s `onClick` will run. +如果你点击任一按钮,它自身的 `onClick` 将首先执行,然后是父级 `
` 的 `onClick` 。所以会出现两条消息。如果你点击 toolbar 本身,只有父级 `
` 的 `onClick` 会执行。 -All events propagate in React except `onScroll`, which only works on the JSX tag you attach it to. +在 React 中所有事件都会传播,除了 `onScroll` ,它仅适用于你附加到的 JSX 标签。 -### Stopping propagation +### 停止传播 {#stopping-propagation} -Event handlers receive an **event object** as their only argument. By convention, it's usually called `e`, which stands for "event." You can use this object to read information about the event. +事件处理函数接收一个 **事件对象** 作为它们唯一的参数。按照惯例,它通常被称为 `e` ,代表 "event"(事件)。你可以使用此对象来读取有关事件的信息。 -That event object also lets you stop the propagation. If you want to prevent an event from reaching parent components, you need to call `e.stopPropagation()` like this `Button` component does: +这个事件对象还允许你停止传播。如果你想阻止一个事件到达父组件,你需要像下面 `Button` 组件那样调用 `e.stopPropagation()` : @@ -384,13 +386,13 @@ function Button({ onClick, children }) { export default function Toolbar() { return (
{ - alert('You clicked on the toolbar!'); + alert('你点击了 toolbar !'); }}> - -
); @@ -407,45 +409,45 @@ button { margin: 5px; }
-When you click on a button: +当你点击按钮时: -1. React calls the `onClick` handler passed to `
``` -Each event propagates in three phases: +每个事件分三个阶段传播: -1. It travels down, calling all `onClickCapture` handlers. -2. It runs the clicked element's `onClick` handler. -3. It travels upwards, calling all `onClick` handlers. +1. 它向下传播,调用所有的 `onClickCapture` 处理函数。 +2. 它执行被点击元素的 `onClick` 处理函数。 +3. 它向上传播,调用所有的 `onClick` 处理函数。 -Capture events are useful for code like routers or analytics, but you probably won't use them in app code. +捕获事件对于路由器或分析等代码很有用,但你可能不会在应用程序代码中使用它们。 -### Passing handlers as alternative to propagation +### 传递处理函数作为传播的替代方案 {#passing-handlers-as-alternative-to-propagation} -Notice how this click handler runs a line of code _and then_ calls the `onClick` prop passed by the parent: +注意这个点击事件处理函数如何执行一行代码 _然后_ 调用父组件传递的 `onClick` prop : ```js {4,5} function Button({ onClick, children }) { @@ -460,22 +462,22 @@ function Button({ onClick, children }) { } ``` -You could add more code to this handler before calling the parent `onClick` event handler, too. This pattern provides an *alternative* to propagation. It lets the child component handle the event, while also letting the parent component specify some additional behavior. Unlike propagation, it's not automatic. But the benefit of this pattern is that you can clearly follow the whole chain code that executes as a result of some event. +你也可以在调用父元素 `onClick` 函数之前向这个处理函数添加更多代码。此模式为传播提供了一个 *替代方案* 。它让子组件处理事件,同时也让父组件指定一些额外的行为。与传播不同,它不是自动的。但是这种模式的好处是,你可以清楚地跟踪作为某个事件执行的整个调用链。 -If you rely on propagation and it's difficult to trace which handlers execute and why, try this approach instead. +如果你依赖于传播,而且很难追踪哪些处理程序在执行,以及执行的原因,可以试试这种方法。 -### Preventing default behavior +### 阻止默认行为 {#preventing-default-behavior} -Some browser events have default behavior associated with them. For example, a `
` submit event, which happens when a button inside of it is clicked, will reload the whole page by default: +某些浏览器事件具有与其关联的默认行为。例如,点击 `` 表单内部的按钮会触发表单提交事件,默认情况下将重新加载整个页面: ```js export default function Signup() { return ( - alert('Submitting!')}> + alert('提交表单!')}> - + ); } @@ -487,7 +489,7 @@ button { margin-left: 5px; }
-You can call `e.preventDefault()` on the event object to stop this from happening: +你可以调用事件对象上的 `e.preventDefault()` 来阻止这种情况发生: @@ -496,10 +498,10 @@ export default function Signup() { return (
{ e.preventDefault(); - alert('Submitting!'); + alert('提交表单!'); }}> - +
); } @@ -511,28 +513,28 @@ button { margin-left: 5px; }
-Don't confuse `e.stopPropagation()` and `e.preventDefault()`. They are both useful, but are unrelated: +不要混淆 `e.stopPropagation()` 和 `e.preventDefault()` 。它们都很有用,但是不相关: -* [`e.stopPropagation()`](https://developer.mozilla.org/docs/Web/API/Event/stopPropagation) stops the event handlers attached to the tags above from firing. -* [`e.preventDefault()` ](https://developer.mozilla.org/docs/Web/API/Event/preventDefault) prevents the default browser behavior for the few events that have it. +* [`e.stopPropagation()`](https://developer.mozilla.org/docs/Web/API/Event/stopPropagation) 停止触发附加到标签之外的事件处理函数。 +* [`e.preventDefault()` ](https://developer.mozilla.org/docs/Web/API/Event/preventDefault) 阻止少数事件的默认浏览器行为。 -## Can event handlers have side effects? +## 事件处理函数可以包含副作用吗? {#can-event-handlers-have-side-effects} -Absolutely! Event handlers are the best place for side effects. +当然了!事件处理函数是产生副作用的最佳位置。 -Unlike rendering functions, event handlers don't need to be [pure](/learn/keeping-components-pure), so it's a great place to *change* something—for example, change an input's value in response to typing, or change a list in response to a button press. However, in order to change some information, you first need some way to store it. In React, this is done by using [state, a component's memory](/learn/state-a-components-memory). You will learn all about it on the next page. +与渲染函数不同,事件处理函数不需要是 [纯函数](/learn/keeping-components-pure) ,因此它是 *更改* 某些内容的好地方——例如,更改输入值以响应键入,或者更改列表以响应按钮按下。但是,为了更改某些信息,你首先需要某种方式存储它。在 React 中,这是通过 [state, a component's memory](/learn/state-a-components-memory) 来完成的。你将在下一页了解所有相关信息。 -* You can handle events by passing a function as a prop to an element like ` ); } @@ -569,7 +571,7 @@ export default function LightSwitch() { -The problem is that ` ); } @@ -594,7 +596,7 @@ export default function LightSwitch() { -Alternatively, you could wrap the call into another function, like ` ); } @@ -621,11 +623,11 @@ export default function LightSwitch() { -### Wire up the events +### 连接事件 {#wire-up-the-events} -This `ColorSwitch` component renders a button. It's supposed to change the page color. Wire it up to the `onChangeColor` event handler prop it receives from the parent so that clicking the button changes the color. +这个 `ColorSwitch` 组件渲染一个按钮。它应该改变页面颜色。将它与从父组件接收的 `onChangeColor` 事件处理函数 prop 连接,以便在点击按钮时改变颜色。 -After you do this, notice that clicking the button also increments the page click counter. Your colleague who wrote the parent component insists that `onChangeColor` does not increment any counters. What else might be happening? Fix it so that clicking the button *only* changes the color, and does _not_ increment the counter. +在你这样做了之后,你会发现点击按钮也会增加页面点击计数器的值。编写父组件的同事坚持 `onChangeColor` 不会增加计数器的值。还发生了什么呢?修复它,使点击按钮 *只* 改变颜色,并且 _不_ 增加计数器。 @@ -635,7 +637,7 @@ export default function ColorSwitch({ }) { return ( ); } @@ -669,7 +671,7 @@ export default function App() {

-

Clicks on the page: {clicks}

+

页面点击次数:{clicks}

); } @@ -679,9 +681,9 @@ export default function App() { -First, you need to add the event handler, like ` ); } @@ -728,7 +730,7 @@ export default function App() {

-

Clicks on the page: {clicks}

+

页面点击次数:{clicks}

); } From 1bbafb451e87236ee02156fe2accf81afeb1b5ba Mon Sep 17 00:00:00 2001 From: QiChang Li Date: Wed, 3 Nov 2021 22:56:37 +0800 Subject: [PATCH 02/13] Update beta/src/pages/learn/responding-to-events.md --- beta/src/pages/learn/responding-to-events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beta/src/pages/learn/responding-to-events.md b/beta/src/pages/learn/responding-to-events.md index 6389ce993c..9678f85b1c 100644 --- a/beta/src/pages/learn/responding-to-events.md +++ b/beta/src/pages/learn/responding-to-events.md @@ -1,7 +1,7 @@ --- title: 响应事件 translators: - - Jiacheng787 + - Jiacheng787 --- From 7032da79313277e3d0f5a347b152a3373cf2af97 Mon Sep 17 00:00:00 2001 From: Jiacheng Dong <43509711+Jiacheng787@users.noreply.github.com> Date: Wed, 3 Nov 2021 23:18:27 +0800 Subject: [PATCH 03/13] Apply suggestions from code review Co-authored-by: QiChang Li --- beta/src/pages/learn/responding-to-events.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/beta/src/pages/learn/responding-to-events.md b/beta/src/pages/learn/responding-to-events.md index 9678f85b1c..1441e9e581 100644 --- a/beta/src/pages/learn/responding-to-events.md +++ b/beta/src/pages/learn/responding-to-events.md @@ -20,7 +20,7 @@ React 允许你在 JSX 中添加事件处理函数。事件处理函数是你自 ## 添加事件处理函数 {#adding-event-handlers} -要添加一个事件处理函数,你需要先定义一个函数,然后 [将它作为 prop 传入](/learn/passing-props-to-a-component) 合适的 JSX 标签。例如,这是一个尚未执行任何操作的按钮: +如需添加一个事件处理函数,你需要先定义一个函数,然后 [将其作为 prop 传入](/learn/passing-props-to-a-component) 合适的 JSX 标签。例如,这里有一个没绑定任何事件的按钮: @@ -28,7 +28,7 @@ React 允许你在 JSX 中添加事件处理函数。事件处理函数是你自 export default function Button() { return ( ); } @@ -36,11 +36,11 @@ export default function Button() { -你可以通过以下三个步骤使它在用户点击时显示消息: +按照如下三个步骤,即可让它在用户点击时显示消息: 1. 在 `Button` 组件 *内部* 声明一个名为 `handleClick` 的函数。 2. 实现函数内部的逻辑(使用 `alert` 来显示消息)。 -3. 添加 `onClick={handleClick}` 到 `