Skip to content

Commit 1e198ad

Browse files
Starriersleviding
authored andcommitted
Translation/bubbling and capturing (javascript-tutorial#161)
* 翻译完成 * 校对信息修改完成 * 语句顺序等部分修改 * Update article.md
1 parent 01b7e2b commit 1e198ad

1 file changed

Lines changed: 80 additions & 80 deletions

File tree

Lines changed: 80 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
# Bubbling and capturing
1+
# 冒泡和捕获
22

3-
Let's start with an example.
3+
我们先看一个示例。
44

5-
This handler is assigned to `<div>`, but also runs if you click any nested tag like `<em>` or `<code>`:
5+
这个处理器被分配给 `<div>`,但是如果你单击像 `<em>` 或者 `<code>` 这样的嵌套标签也是可以运行的:
66

77
```html autorun height=60
88
<div onclick="alert('The handler!')">
99
<em>If you click on <code>EM</code>, the handler on <code>DIV</code> runs.</em>
1010
</div>
1111
```
1212

13-
Isn't it a bit strange? Why the handler on `<div>` runs if the actual click was on `<em>`?
13+
这很奇怪不是么?为什么实际上是单击 `<em>`,而 `<div>` 上的处理器会运行?
1414

15-
## Bubbling
15+
## 冒泡
1616

17-
The bubbling principle is simple.
17+
冒泡原理很简单。
1818

19-
**When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.**
19+
**当事件发生在元素上,它首先会运行元素本身的处理器,然后运行父元素上的,再然后是其他祖先上的**
2020

21-
Let's say, we have 3 nested elements `FORM > DIV > P` with a handler on each of them:
21+
比如我们有 3 层嵌套 `FORM > DIV > P`,它们都各自拥有一个处理器:
2222

2323
```html run autorun
2424
<style>
@@ -35,57 +35,57 @@ Let's say, we have 3 nested elements `FORM > DIV > P` with a handler on each of
3535
</form>
3636
```
3737

38-
A click on the inner `<p>` first runs `onclick`:
39-
1. On that `<p>`.
40-
2. Then on the outer `<div>`.
41-
3. Then on the outer `<form>`.
42-
4. And so on upwards till the `document` object.
38+
单击内部 `<p>` 会首先运行 `onclick`
39+
1. `<p>` 上。
40+
2. 然后是外部的 `<div>`
41+
3. 再然后是外部的 `<form>`
42+
4. 以此类推,直到最后的 `document` 对象。
4343

4444
![](event-order-bubbling.png)
4545

46-
So if we click on `<p>`, then we'll see 3 alerts: `p` -> `div` -> `form`.
46+
因此,如果我们单击 `<p>`,那么我们将看到 3 个警告: `p` -> `div` -> `form`
4747

48-
The process is called "bubbling", because events "bubble" from the inner element up through parents like a bubble in the water.
48+
这个过程被称为“冒泡”,因为事件“冒泡”从内部元素向上时,会经过父节点,就像水里的气泡一样。
4949

5050
```warn header="*Almost* all events bubble."
51-
The key word in this phrase is "almost".
51+
这个短语的关键词是“几乎”。
5252
53-
For instance, a `focus` event does not bubble. There are other examples too, we'll meet them. But still it's an exception, rather than a rule, most events do bubble.
53+
例如,`focus` 事件不会冒泡。同样,我们以后还会遇到其他例子。但是这是例外,而不是规则,因为大多数事件都是冒泡的。
5454
```
5555

5656
## event.target
5757

58-
A handler on a parent element can always get the details about where it actually happened.
58+
父元素上的处理器总是可以获取事件实际发生位置的详细信息。
5959

60-
**The most deeply nested element that caused the event is called a *target* element, accessible as `event.target`.**
60+
**引发事件的那个嵌套层级最深的元素被称为目标元素,可通过 `event.target` 访问。**
6161

62-
Note the differences from `this` (=`event.currentTarget`):
62+
注意与 `this` (=`event.currentTarget`) 之间的区别:
6363

64-
- `event.target` -- is the "target" element that initiated the event, it doesn't change through the bubbling process.
65-
- `this` -- is the "current" element, the one that has a currently running handler on it.
64+
- `event.target` —— 是引发事件的目标元素,它在冒泡过程中不会发生变化。。
65+
- `this` —— 是 "current" 元素,其中有一个当前正在运行的处理器。
6666

67-
For instance, if we have a single handler `form.onclick`, then it can "catch" all clicks inside the form. No matter where the click happened, it bubbles up to `<form>` and runs the handler.
67+
例如,如果我们有一个 `form.onclick` 处理器,那么它可以“抓”到所有表单内部元素上的点击事件。无论点击发生在哪里,它都会冒泡到 `<form>` 然后运行处理器。
6868

69-
In `form.onclick` handler:
69+
`form.onclick` 处理器:
7070

71-
- `this` (`=event.currentTarget`) is the `<form>` element, because the handler runs on it.
72-
- `event.target` is the concrete element inside the form that actually was clicked.
71+
- `this` (`=event.currentTarget`) `<form>` 元素,因为处理器在它上面运行。
72+
- `event.target` 是表单中实际上被单击的元素。
7373

74-
Check it out:
74+
检查:
7575

7676
[codetabs height=220 src="bubble-target"]
7777

78-
It's possible that `event.target` equals `this` -- when the click is made directly on the `<form>` element.
78+
`event.target` 可能会等于 `this` —— 当单击事件发生在 `<form>` 元素上时。
7979

80-
## Stopping bubbling
80+
## 停止冒泡
8181

82-
A bubbling event goes from the target element straight up. Normally it goes upwards till `<html>`, and then to `document` object, and some events even reach `window`, calling all handlers on the path.
82+
冒泡事件从目标元素开始向上冒泡。通常情况下,它向上上升到 `<html>`,然后再到 `document` 对象,一些事件甚至到达了 `window`,它们会调用路径上的所有处理器。
8383

84-
But any handler may decide that the event has been fully processed and stop the bubbling.
84+
但是任何处理器都可以决定事件已经被完全处理,然后停止冒泡。
8585

86-
The method for it is `event.stopPropagation()`.
86+
方法是 `event.stopPropagation()`
8787

88-
For instance, here `body.onclick` doesn't work if you click on `<button>`:
88+
例如,如果你单击 `<button>` 这里的 `body.onclick` 是无效的:
8989

9090
```html run autorun height=60
9191
<body onclick="alert(`the bubbling doesn't reach here`)">
@@ -94,60 +94,60 @@ For instance, here `body.onclick` doesn't work if you click on `<button>`:
9494
```
9595

9696
```smart header="event.stopImmediatePropagation()"
97-
If an element has multiple event handlers on a single event, then even if one of them stops the bubbling, the other ones still execute.
97+
如果元素在事件上有多个处理器,那么即使其中一个事件处理器停止冒泡,其他处理器也会继续执行。
9898
99-
In other words, `event.stopPropagation()` stops the move upwards, but on the current element all other handlers will run.
99+
换句话说,`event.stopPropagation()` 停止向上移动,但是当前元素上的其他处理器都会继续运行。
100100
101-
To stop the bubbling and prevent handlers on the current element from running, there's a method `event.stopImmediatePropagation()`. After it no other handlers execute.
101+
为了停止事件冒泡并阻止当前元素上的处理器运行,有一个 `event.stopImmediatePropagation()` 方法。使用之后,其他处理器就不会被执行。
102102
```
103103

104104
```warn header="Don't stop bubbling without a need!"
105-
Bubbling is convenient. Don't stop it without a real need: obvious and architecturally well-thought.
105+
冒泡很方便。不要在没有真正需求的时候阻止它:除非是显而易见的,或者是在架构上经过深思熟虑后。
106106
107-
Sometimes `event.stopPropagation()` creates hidden pitfalls that later may become problems.
107+
有时 `event.stopPropagation()` 会产生隐藏的陷阱,这可能会成为以后的问题。
108108
109-
For instance:
109+
例如:
110110
111-
1. We create a nested menu. Each submenu handles clicks on its elements and calls `stopPropagation` so that outer menu don't trigger.
112-
2. Later we decide to catch clicks on the whole window, to track users' behavior (where people click). Some analytic systems do that. Usually the code uses `document.addEventListener('click'…)` to catch all clicks.
113-
3. Our analytic won't work over the area where clicks are stopped by `stopPropagation`. We've got a "dead zone".
111+
1. 我们创建一个嵌套目录,每个子目录各自处理对自己的单击事件,并调用 `stopPropagation`,这样外层目录就不会被触发。
112+
2. 之后我们决定去捕获在整个窗口上的点击,来追踪用户的行为(用户点击了哪里)。有些分析系统会这样做。通常代码会使用 `document.addEventListener('click'…)` 来捕获所有的点击。
113+
3. 我们的分析不适用于点击被 `stopPropagation` 所阻止的区域。我们有一个 "dead zone"
114114
115-
There's usually no real need to prevent the bubbling. A task that seemingly requires that may be solved by other means. One of them is to use custom events, we'll cover them later. Also we can write our data into the `event` object in one handler and read it in another one, so we can pass to handlers on parents information about the processing below.
115+
通常没有必要去阻止冒泡的产生。看似需要的任务,可以通过其他方法解决。其中之一就是使用自定义事件,我们稍后会进行讨论。此外,我们还可以将数据写入一个处理器中的 `event` 对象,并在另一个处理器中读取它,这样我们就可以向父处理器传递有关下层处理器的信息。
116116
```
117117

118118

119-
## Capturing
119+
## 捕获
120120

121-
There's another phase of event processing called "capturing". It is rarely used in real code, but sometimes can be useful.
121+
还有另一阶段的事件过程称为“捕获”。它在代码中很少被使用,但是有时是有用的。
122122

123-
The standard [DOM Events](http://www.w3.org/TR/DOM-Level-3-Events/) describes 3 phases of event propagation:
123+
[DOM 事件](http://www.w3.org/TR/DOM-Level-3-Events/)标准描述了事件传播的 3 个阶段:
124124

125-
1. Capturing phase -- the event goes down to the element.
126-
2. Target phase -- the event reached the target element.
127-
3. Bubbling phase -- the event bubbles up from the element.
125+
1. 捕获阶段 —— 事件(从 Window)向下到达元素上。
126+
2. 目标阶段 —— 事件到达目标元素。
127+
3. 冒泡阶段 —— 事件从元素上开始冒泡。
128128

129-
Here's the picture of a click on `<td>` inside a table, taken from the specification:
129+
下面是在表格中单击 `<td>` 的图片,取自规范:
130130

131131
![](eventflow.png)
132132

133-
That is: for a click on `<td>` the event first goes through the ancestors chain down to the element (capturing), then it reaches the target, and then it goes up (bubbles), calling handlers on its way.
133+
即:对于 `<td>` 的单击,事件首先通过祖先链向下传递到元素(捕获),然后到达目标,最后上升(冒泡),在途中调用处理器。
134134

135-
**Before we only talked about bubbling, because the capturing phase is rarely used. Normally it is invisible to us.**
135+
**我们之前只讨论了冒泡,因为捕获阶段很少被使用。通常情况下,它对我们不可见**
136136

137-
Handlers added using `on<event>`-property or using HTML attributes or using `addEventListener(event, handler)` don't know anything about capturing, they only run on the 2nd and 3rd phases.
137+
处理器 `on<event>` 属性或使用 HTML 属性或者使用 `addEventListener(event, handler)` 添加的处理器,不知道捕获,它们只知道第 2 和第 3 阶段。
138138

139-
To catch an event on the capturing phase, we need to set the 3rd argument of `addEventListener` to `true`.
139+
要在捕获阶段捕获事件,我们需要将 `addEventListener` 的第三个参数设置为 `true`
140140

141-
There are two possible values for that optional last argument:
141+
最后一个参数是可选的,有两个可能的值:
142142

143-
- If it's `false` (default), then the handler is set on the bubbling phase.
144-
- If it's `true`, then the handler is set on the capturing phase.
143+
- 如果为 `false`(默认值),则在冒泡阶段设置处理器。
144+
- 如果为 `true`,则在捕获阶段设置处理器。
145145

146-
Note that while formally there are 3 phases, the 2nd phase ("target phase": the event reached the element) is not handled separately: handlers on both capturing and bubbling phases trigger at that phase.
146+
注意,虽然形式上有 3 个阶段,但第 2 阶段(“目标阶段”:事件到达元素)没有单独被处理:捕获阶段和冒泡阶段的处理器在该阶段都会被触发。
147147

148-
If one puts capturing and bubbling handlers on the target element, the capture handler triggers last in the capturing phase and the bubble handler triggers first in the bubbling phase.
148+
如果将捕获阶段和冒泡阶段处理器放在目标上,捕获阶段处理器将在捕获阶段触发,而冒泡处理器将首先在冒泡阶段被触发。
149149

150-
Let's see it in action:
150+
我们看一下效果:
151151

152152
```html run autorun height=140 edit
153153
<style>
@@ -171,37 +171,37 @@ Let's see it in action:
171171
</script>
172172
```
173173

174-
The code sets click handlers on *every* element in the document to see which ones are working.
174+
代码为文档中的**每个**元素设置点击处理器,以查看哪些元素上的点击事件处理器生效了。
175175

176-
If you click on `<p>`, then the sequence is:
176+
如果你点击了 `<p>`,那么顺序是:
177177

178-
1. `HTML` -> `BODY` -> `FORM` -> `DIV` -> `P` (capturing phase, the first listener), and then:
179-
2. `P` -> `DIV` -> `FORM` -> `BODY` -> `HTML` (bubbling phase, the second listener).
178+
1. `HTML` -> `BODY` -> `FORM` -> `DIV` -> `P`(捕获阶段,第一个监听者),然后:
179+
2. `P` -> `DIV` -> `FORM` -> `BODY` -> `HTML`(冒泡阶段,第二个监听者)。
180180

181-
Please note that `P` shows up two times: at the end of capturing and at the start of bubbling.
181+
请注意,`P` 出现了两次:在捕获结束和开始冒泡时。
182182

183-
There's a property `event.eventPhase` that tells us the number of the phase on which the event was caught. But it's rarely used, because we usually know it in the handler.
183+
有一个 `event.eventPhase` 属性,它告诉我们事件被捕获阶段的数量。但它很少使用,因为我们通常在处理器中了解到它。
184184

185-
## Summary
185+
## 总结
186186

187-
The event handling process:
187+
事件处理过程:
188188

189-
- When an event happens -- the most nested element where it happens gets labeled as the "target element" (`event.target`).
190-
- Then the event first moves from the document root down the `event.target`, calling handlers assigned with `addEventListener(...., true)` on the way.
191-
- Then the event moves from `event.target` up to the root, calling handlers assigned using `on<event>` and `addEventListener` without the 3rd argument or with the 3rd argument `false`.
189+
- 当事件发生时 —— 嵌套最深的那个元素被标记为“目标事件”(`event.target`)
190+
- 然后事件先从文档根节点向下移动到 `event.target`,过程中调用分配给 `addEventListener(...., true)` 的处理器。
191+
- 再然后事件从 `event.target` 向上移动到根,调用使用 `on<event>` `addEventListener` 分配的处理器,不使用第三个参数或第三个参数设置为 `false`
192192

193-
Each handler can access `event` object properties:
193+
每个处理器都可以访问 `event` 对象属性:
194194

195-
- `event.target` -- the deepest element that originated the event.
196-
- `event.currentTarget` (=`this`) -- the current element that handles the event (the one that has the handler on it)
197-
- `event.eventPhase` -- the current phase (capturing=1, bubbling=3).
195+
- `event.target` —— 事件最深的元素。
196+
- `event.currentTarget` (=`this`) —— 处理事件的当前元素(有处理器在其上运行的)
197+
- `event.eventPhase` —— 当前阶段(capturing=1, bubbling=3)。
198198

199-
Any event handler can stop the event by calling `event.stopPropagation()`, but that's not recommended, because we can't really be sure we won't need it above, maybe for completely different things.
199+
任何事件处理器都可以通过调用 `event.stopPropagation()` 来停止事件,但不建议如此,因为我们不确定是否后续会使用冒泡上来的事件,也许是完全不同的事情。
200200

201-
The capturing phase is used very rarely, usually we handle events on bubbling. And there's a logic behind that.
201+
捕获阶段很少使用,我们通常处理冒泡事件。这背后有一个逻辑。
202202

203-
In real world, when an accident happens, local authorities react first. They know best the area where it happened. Then higher-level authorities if needed.
203+
现实世界中,当事故发生时,当地警方第一时间作出反应。他们最了解发生这件事的地方。如果需要更高级别的权威。那么就会向上申请。
204204

205-
The same for event handlers. The code that set the handler on a particular element knows maximum details about the element and what it does. A handler on a particular `<td>` may be suited for that exactly `<td>`, it knows everything about it, so it should get the chance first. Then its immediate parent also knows about the context, but a little bit less, and so on till the very top element that handles general concepts and runs the last.
205+
事件处理却也是如此。在特定元素上设置处理器的代码了解该元素最详尽的信息。特定 `<td>` 上的处理器可能恰好适合于 `<td>`,它知道关于它的一切。所以它应该首先获得机会。然后,它的直系父节点也会获取上下文,但是会少一些,以此类推。而最顶层的元素最后才获取到信息,且只能了解到大致的情况。
206206

207-
Bubbling and capturing lay the foundation for "event delegation" -- an extremely powerful event handling pattern that we study in the next chapter.
207+
冒泡和捕获为“事件委托”奠定了基础 —— 我们将在下一章中研究非常强大的事件处理模式。

0 commit comments

Comments
 (0)