From 9dbf9c9681edf42ed5ff38594c2d568ff3e700dc Mon Sep 17 00:00:00 2001
From: mdn-bot <108879845+mdn-bot@users.noreply.github.com>
Date: Tue, 2 Jul 2024 01:29:27 +0000
Subject: [PATCH 1/5] zh-cn: sync translated content
---
files/zh-cn/_redirects.txt | 1 +
files/zh-cn/_wikihistory.json | 8 ++++----
.../javascript/building_blocks/event_bubbling}/index.md | 3 ++-
3 files changed, 7 insertions(+), 5 deletions(-)
rename files/zh-cn/{web/api/event/comparison_of_event_targets => learn/javascript/building_blocks/event_bubbling}/index.md (98%)
diff --git a/files/zh-cn/_redirects.txt b/files/zh-cn/_redirects.txt
index cf3da9a7daed40..5d555b258605bf 100644
--- a/files/zh-cn/_redirects.txt
+++ b/files/zh-cn/_redirects.txt
@@ -1470,6 +1470,7 @@
/zh-CN/docs/Web/API/Element/pointerlockchange_event /zh-CN/docs/Web/API/Document/pointerlockchange_event
/zh-CN/docs/Web/API/Element/removeAttributre /zh-CN/docs/Web/API/Element/removeAttribute
/zh-CN/docs/Web/API/Element/select_event /zh-CN/docs/Web/API/HTMLInputElement/select_event
+/zh-CN/docs/Web/API/Event/Comparison_of_Event_Targets /zh-CN/docs/Learn/JavaScript/Building_blocks/Event_bubbling
/zh-CN/docs/Web/API/Event/CustomEvent /zh-CN/docs/Web/API/CustomEvent
/zh-CN/docs/Web/API/Event/pageY /zh-CN/docs/Web/API/MouseEvent/pageY
/zh-CN/docs/Web/API/Event/禁用时间冒泡 /zh-CN/docs/Web/API/Event/cancelBubble
diff --git a/files/zh-cn/_wikihistory.json b/files/zh-cn/_wikihistory.json
index 9d8dcc3e38b795..0188b12a688df3 100644
--- a/files/zh-cn/_wikihistory.json
+++ b/files/zh-cn/_wikihistory.json
@@ -3557,6 +3557,10 @@
"ppphp"
]
},
+ "Learn/JavaScript/Building_blocks/Event_bubbling": {
+ "modified": "2019-03-18T21:17:15.255Z",
+ "contributors": ["zhuangyin"]
+ },
"Learn/JavaScript/Building_blocks/Events": {
"modified": "2020-08-04T06:06:58.173Z",
"contributors": [
@@ -9177,10 +9181,6 @@
"TigerSoldier"
]
},
- "Web/API/Event/Comparison_of_Event_Targets": {
- "modified": "2019-03-18T21:17:15.255Z",
- "contributors": ["zhuangyin"]
- },
"Web/API/Event/Event": {
"modified": "2020-10-15T21:37:04.498Z",
"contributors": [
diff --git a/files/zh-cn/web/api/event/comparison_of_event_targets/index.md b/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md
similarity index 98%
rename from files/zh-cn/web/api/event/comparison_of_event_targets/index.md
rename to files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md
index 40cf37237cbdb1..20bfdace349442 100644
--- a/files/zh-cn/web/api/event/comparison_of_event_targets/index.md
+++ b/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md
@@ -1,6 +1,7 @@
---
title: Comparison of Event Targets
-slug: Web/API/Event/Comparison_of_Event_Targets
+slug: Learn/JavaScript/Building_blocks/Event_bubbling
+original_slug: Web/API/Event/Comparison_of_Event_Targets
---
{{ ApiRef() }}
From 7e1c3aa57e6137e446a0a23d48ed7e8f4f44a6c4 Mon Sep 17 00:00:00 2001
From: Jason Ren <40999116+jasonren0403@users.noreply.github.com>
Date: Tue, 2 Jul 2024 07:30:07 +0000
Subject: [PATCH 2/5] resolve flaws
---
.../building_blocks/event_bubbling/index.md | 25 +++++++++----------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md b/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md
index 20bfdace349442..12ea97f72f308c 100644
--- a/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md
+++ b/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md
@@ -1,10 +1,9 @@
---
-title: Comparison of Event Targets
+title: 事件冒泡
slug: Learn/JavaScript/Building_blocks/Event_bubbling
-original_slug: Web/API/Event/Comparison_of_Event_Targets
---
-{{ ApiRef() }}
+{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Events","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}
### Event targets
@@ -20,10 +19,10 @@ There are 5 targets to consider:
- event.originalTarget
+ event.originalTarget
Date: Tue, 2 Jul 2024 07:50:22 +0000
Subject: [PATCH 3/5] separate bubbling and event main docs
---
.../building_blocks/event_bubbling/index.md | 538 +++++++++++-------
.../building_blocks/events/index.md | 357 +-----------
2 files changed, 348 insertions(+), 547 deletions(-)
diff --git a/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md b/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md
index 12ea97f72f308c..5c6311e9a2771f 100644
--- a/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md
+++ b/files/zh-cn/learn/javascript/building_blocks/event_bubbling/index.md
@@ -5,206 +5,360 @@ slug: Learn/JavaScript/Building_blocks/Event_bubbling
{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Events","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}
-### Event targets
-
-It's easy to get confused about which target to examine when writing an event handler. This article should clarify the use of the target properties.
-
-There are 5 targets to consider:
-
-
-
-
- Property
- Defined in
- Purpose
-
-
- event.target
-
- DOM Event Interface
-
-
-
- The DOM element on the lefthand side of the call that triggered this
- event, eg:
-
- element .dispatchEvent(event )
-
-
-
-
- event.currentTarget
-
- DOM Event Interface
-
-
- The
- EventTarget
- whose
- EventListeners
- are currently being processed. As the event capturing and bubbling
- occurs this value changes.
-
-
-
- event.relatedTarget
-
- DOM MouseEvent Interface
-
- Identifies a secondary target for the event.
-
-
-
- event.explicitOriginalTarget
-
-
- Event.webidl
-
-
- {{ Non-standard_inline() }} If the event was retargeted for
- some reason other than an anonymous boundary crossing, this will be set
- to the target before the retargeting occurs. For example, mouse events
- are retargeted to their parent node when they happen over text nodes
- ([Firefox bug 185889](https://bugzil.la/185889)), and in that case .target
will
- show the parent and .explicitOriginalTarget
will show the
- text node. Unlike .originalTarget
,
- .explicitOriginalTarget
will never contain anonymous
- content.
-
-
-
- event.originalTarget
-
- Event.webidl
-
-
- {{ Non-standard_inline() }} The original target of the event,
- before any retargetings. See
- Anonymous Content#Event_Flow_and_Targeting
- for details.
-
-
-
-
-
-### Use of `explicitOriginalTarget` and `originalTarget`
-
-TODO: Only available in a Mozilla-based browser? TODO: Only suitable for extension-developers?
-
-### Examples
-
-```
-
-
-
-
-
- Comparison of Event Targets
-
-
+## 事件冒泡
+
+事件冒泡描述了浏览器如何处理针对嵌套元素的事件。
+
+### 在父元素上设置监听器
+
+考虑像这样的网页:
+
+```html
+
+ 点我!
+
+
+```
+
+这里有一个在其他元素({{HTMLElement("div")}})内部的按钮,可以说这里的 `` 元素是其中包含元素的**父元素**。当我们在父元素附加单击事件处理器,并点击按钮时,会发生什么?
+
+```js
+const output = document.querySelector("#output");
+function handleClick(e) {
+ output.textContent += `你在 ${e.currentTarget.tagName} 元素上进行了点击\n`;
+}
+
+const container = document.querySelector("#container");
+container.addEventListener("click", handleClick);
+```
+
+{{ EmbedLiveSample('在父元素上设置监听器', '100%', 200, "", "") }}
+
+你会发现在用户单击按钮时,父元素上触发了单击事件:
+
+```
+你在 DIV 元素上进行了点击
+```
+
+这是有道理的:按钮在 `
` 里面,所以当你点击按钮的时候,你也隐含地点击了它所在的元素。
+
+### 冒泡示例
+
+如果在按钮*及*其父元素上同时添加事件处理器,会发生什么?
+
+```html
+
+
+ 点我!
+
+
+
+```
+
+让我们试着给按钮、它的父元素(`
`)以及包含它们的 {{HTMLElement("body")}} 元素添加点击事件处理器:
+
+```js
+const output = document.querySelector("#output");
+function handleClick(e) {
+ output.textContent += `你在 ${e.currentTarget.tagName} 元素上进行了点击\n`;
+}
+
+const container = document.querySelector("#container");
+const button = document.querySelector("button");
+
+document.body.addEventListener("click", handleClick);
+container.addEventListener("click", handleClick);
+button.addEventListener("click", handleClick);
+```
+
+{{ EmbedLiveSample('冒泡', '100%', 200, "", "") }}
+
+你会发现在用户单击按钮时,所有三个元素都触发了单击事件:
+
+```
+你在 BUTTON 元素上进行了点击
+你在 DIV 元素上进行了点击
+你在 BODY 元素上进行了点击
+```
+
+在这种情况下:
+
+- 最先触发按钮上的单击事件
+- 然后是按钮的父元素(`
` 元素)
+- 然后是 `
` 的父元素(`` 元素)
+
+我们可以这样描述:事件从被点击的最里面的元素**冒泡**而出。
+
+这种行为可能是有用的,也可能引起意想不到的问题。在接下来的章节中,我们将看到它引起的一个问题,并找到解决方案。
+
+### 视频播放器示例
+
+在这个示例中,我们的页面包含一个视频,最初它为隐藏状态;还有一个标记为“显示视频”的按钮。我们希望有如下交互:
+
+- 当用户单击“显示视频”按钮时,显示包含视频的盒子,但不要开始播放视频。
+- 当用户在视频上单击时,开始播放视频。
+- 当用户单击盒子内视频以外的任何区域时,隐藏盒子。
+
+HTML 代码看起来像这样:
+
+```html
+
显示视频
+
+
+
+
+
+ 你的浏览器不支持 HTML 视频,这里有视频的替代链接 。
+
+
+
+```
+
+它包含:
+
+- 一个 `
` 元素
+- 一个 `` 元素,最初其包含 `class="hidden"` 属性
+- 一个嵌套在 `
` 元素中的 `
` 元素
+
+我们使用 CSS 来隐藏具有 `"hidden"` 类的元素。
+
+```css hidden
+div {
+ width: 100%;
+ height: 100%;
+ background-color: #eee;
+}
+
+.hidden {
+ display: none;
+}
+
+div video {
+ padding: 40px;
+ display: block;
+ width: 400px;
+ margin: 40px auto;
+}
+```
+
+JavaScript 代码看起来像这样:
+
+```js
+const btn = document.querySelector("button");
+const box = document.querySelector("div");
+const video = document.querySelector("video");
+
+btn.addEventListener("click", () => box.classList.remove("hidden"));
+video.addEventListener("click", () => video.play());
+box.addEventListener("click", () => box.classList.add("hidden"));
+```
+
+它添加了三个 `'click'` 事件处理器:
+
+- 一个在 `` 上,它显示了包含 `` 的 ``
+- 一个在 `
` 上,用于开始播放视频
+- 一个在 `` 上,用于隐藏视频
+
+让我们看看这个如何工作:
+
+{{ EmbedLiveSample('视频播放器示例', '100%', 500) }}
+
+你应该看到,当你点击按钮时,盒子和它所包含的视频都显示出来。但当你点击视频时,视频开始播放,但盒子又被隐藏起来了!
+
+视频在 `
` 内(是它的一部分),所以点击视频会*同时*运行两个事件处理器,导致这种行为。
+
+### 使用 stopPropagation() 修复问题
+
+正如我们在上一节所看到的,事件冒泡有时会产生问题,但有一种方法可以防止这些问题。[`Event`](/zh-CN/docs/Web/API/Event) 对象有一个可用的函数,叫做 [`stopPropagation()`](/zh-CN/docs/Web/API/Event/stopPropagation),当在一个事件处理器中调用时,可以防止事件向任何其他元素传递。
+
+我们可以通过修改 JavaScript 代码来修复当前的问题:
+
+```js
+const btn = document.querySelector("button");
+const box = document.querySelector("div");
+const video = document.querySelector("video");
+
+btn.addEventListener("click", () => box.classList.remove("hidden"));
+
+video.addEventListener("click", (event) => {
+ event.stopPropagation();
+ video.play();
+});
+
+box.addEventListener("click", () => box.classList.add("hidden"));
+```
+
+我们在这里所做的是在 `
` 元素的 `'click'` 事件的处理器中对事件对象调用 `stopPropagation()`。这将阻止该事件向盒子内传递。现在试着点击按钮,然后再点击视频:
+
+{{EmbedLiveSample("使用 stopPropagation() 修复问题", '100%', 500)}}
+
+```html hidden
+显示视频
+
+
+
+
+
+ 你的浏览器不支持 HTML 视频,这里有视频的替代链接 。
+
+
+
+```
+
+```css hidden
+div {
+ width: 100%;
+ height: 100%;
+ background-color: #eee;
+}
+
+.hidden {
+ display: none;
+}
+
+div video {
+ padding: 40px;
+ display: block;
+ width: 400px;
+ margin: 40px auto;
+}
+```
+
+### 事件捕获
+
+事件传播的另一种形式是*事件捕获*。这就像事件冒泡,但顺序是相反的:事件不是先在最内层的目标元素上发生,然后在连续较少的嵌套元素上发生,而是先在*最小嵌套*元素上发生,然后在连续更多的嵌套元素上发生,直到达到目标。
+
+事件捕获默认是禁用的,你需要在 `addEventListener()` 的 `capture` 选项中启用它。
+
+以下示例类似于之前看到的[冒泡示例](#冒泡示例),除了使用了 `capture` 选项以外:
+
+```html
-
-
-
- Original target dispatching the event event.target
- Target who's event listener is being processed event.currentTarget
- Identify other element (if any) involved in the event event.relatedTarget
- If there was a retargetting of the event for some reason event.explicitOriginalTarget contains the target before retargetting (never contains anonymous targets)
- If there was a retargetting of the event for some reason event.originalTarget contains the target before retargetting (may contain anonymous targets)
-
-
-
-
-
-
-
-
-
-
-Clicking on the text will show the difference between explicitOriginalTarget, originalTarget and target
-
+
+ 点我!
+
+
-
```
-### Use of `target` and `relatedTarget`
+```js
+const output = document.querySelector("#output");
+function handleClick(e) {
+ output.textContent += `你在 ${e.currentTarget.tagName} 元素上进行了点击\n`;
+}
+
+const container = document.querySelector("#container");
+const button = document.querySelector("button");
+
+document.body.addEventListener("click", handleClick, { capture: true });
+container.addEventListener("click", handleClick, { capture: true });
+button.addEventListener("click", handleClick);
+```
+
+{{ EmbedLiveSample('事件捕获', '100%', 200, "", "") }}
+
+在这种情况下,消息出现的顺序发生了颠倒:`` 事件处理器首先触发,然后是 `` 的,最后是 `
` 的:
+
+```
+你在 BODY 元素上进行了点击
+你在 DIV 元素上进行了点击
+你在 BUTTON 元素上进行了点击
+```
+
+为什么要同时使用捕获和冒泡功能?在过去的坏日子里,当浏览器的交叉兼容性远不如现在时,Netscape 只使用事件捕捉,而 Internet Explorer 只使用事件冒泡。当 W3C 决定尝试将行为标准化并达成共识时,他们最终确定了这个包括这两种行为的系统,这也是现代浏览器所实现的。
+
+默认情况下,几乎所有的事件处理程序都是在冒泡阶段注册的,这在大多数情况下更有意义。
-The `relatedTarget` property for the `mouseover` event holds the node that the mouse was previously over. For the `mouseout` event, it holds the node that the mouse moved to.
+## 事件委托
-| Event type | [event.target](/zh-CN/DOM/event.target) | [event.relatedTarget](/zh-CN/DOM/event.relatedTarget) |
-| ----------- | ------------------------------------------------- | ----------------------------------------------------- |
-| `mouseover` | the EventTarget which the pointing device entered | the EventTarget which the pointing device exited |
-| `mouseout` | the EventTarget which the pointing device exited | the EventTarget which the pointing device entered |
+在上一节中,我们看了一个由事件冒泡引起的问题以及如何解决它。不过,事件冒泡并不只是令人讨厌:它可以非常有用。特别是,它可以实现**事件委托**。在这种做法中,当我们想在用户与大量的子元素中的任何一个互动时运行一些代码时,我们在它们的父元素上设置事件监听器,让发生在它们身上的事件冒泡到它们的父元素上,而不必在每个子元素上单独设置事件监听器。
-TODO: Also needs descriptions about `dragenter` and `dragexit` events.
+让我们回到第一个例子,当用户点击一个按钮时,我们设置整个页面的背景颜色。假设取而代之的是,页面被分为 16 个区域,我们想在用户点击每个区域时将其设置为随机颜色。
-#### Example
+这里是 HTML 代码:
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
```
-
-
-
+
+我们有一些 CSS 代码,来设置每一个区域的尺寸和位置:
+
+```css
+.tile {
+ height: 100px;
+ width: 25%;
+ float: left;
+}
+```
+
+在 JavaScript 代码中,我们向每一个区域中添加单击事件处理器。但是,一个更简单、更有效的选择是在父节点上设置点击事件处理器,并依靠事件冒泡来确保用户点击每个区域时处理程序被执行:
+
+```js
+function random(number) {
+ return Math.floor(Math.random() * number);
+}
+
+function bgChange() {
+ const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
+ return rndCol;
+}
+
+const container = document.querySelector("#container");
+
+container.addEventListener("click", (event) => {
+ event.target.style.backgroundColor = bgChange();
+});
```
+
+示例输出如下(试着随便点击):
+
+{{ EmbedLiveSample('事件委托', '100%', 430, "", "") }}
+
+> **备注:** 在这个例子中,我们使用 `event.target` 来获取事件的目标元素(也就是最里面的元素)。如果我们想访问处理这个事件的元素(在这个例子中是容器),我们可以使用 `event.currentTarget`。
+
+> **备注:** 完整的源代码见 [useful-eventtarget.html](https://github.com/mdn/learning-area/blob/main/javascript/building-blocks/events/useful-eventtarget.html);也可以在这里[在线运行它](https://mdn.github.io/learning-area/javascript/building-blocks/events/useful-eventtarget.html)。
+
+## 技能测试!
+
+你已经到了本文的结尾,但你能记住最重要的信息吗?在你继续前进之前,要验证你是否记住了这些信息,请前往[技能测试:事件](/zh-CN/docs/Learn/JavaScript/Building_blocks/Test_your_skills:_Events)页面进行测试。
+
+## 结论
+
+现在你应该知道在这个早期阶段需要了解的所有 web 事件。如上所述,事件并不是 JavaScript 的核心部分——它们是在浏览器 Web API 中定义的。
+
+另外,理解 JavaScript 在不同环境下使用不同的事件模型很重要——从 Web API 到其他领域,如浏览器 WebExtensions 和 Node.js(服务器端 JavaScript)。我们并不期望现在了解所有这些领域,但是当你在学习 web 开发的过程中,理解这些事件的基础是很有帮助的。
+
+> **备注:** 如果你遇到了问题,可以向我们其中的一个[交流渠道](/zh-CN/docs/MDN/Community/Communication_channels)寻求帮助。
+
+## 参见
+
+- [domevents.dev](https://domevents.dev/)——一个非常有用的交互式游乐场应用程序,能够通过探索来学习 DOM 事件系统的行为。
+- [事件参考](/zh-CN/docs/Web/Events)
+- [事件顺序](https://www.quirksmode.org/js/events_order.html)(探讨了捕获和冒泡)——由 Peter-Paul Koch 撰写的非常详尽的文章。
+
+{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Events","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}
diff --git a/files/zh-cn/learn/javascript/building_blocks/events/index.md b/files/zh-cn/learn/javascript/building_blocks/events/index.md
index 98fcb7eefbadde..79c12cbcf21e5d 100644
--- a/files/zh-cn/learn/javascript/building_blocks/events/index.md
+++ b/files/zh-cn/learn/javascript/building_blocks/events/index.md
@@ -3,7 +3,7 @@ title: 事件介绍
slug: Learn/JavaScript/Building_blocks/Events
---
-{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}
+{{LearnSidebar}}{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Event_bubbling", "Learn/JavaScript/Building_blocks")}}
事件是你正在编程的系统中发生的事情,系统会告诉你有关这些事件的信息,以便你的代码能够对它们做出反应。
@@ -300,8 +300,6 @@ btn.addEventListener("click", bgChange);
在这里,可以看到我们在函数中包括一个事件对象 `e`,并在函数中设置背景颜色样式在 `e.target` 上——它指的是按钮本身。事件对象 `e` 的 `target` 属性始终是事件刚刚发生的元素的引用。所以在这个例子中,我们在按钮上设置一个随机的背景颜色,而不是页面。
-> **备注:** 参见[事件委托](#事件委托)来了解使用 `event.target` 的示例。
-
> **备注:** 可以使用任何喜欢的名称作为事件对象——只需要选择一个名称,然后可以在事件处理函数中引用它。开发人员最常使用 `e`/`evt`/`event`,因为它们很简单易记。保持一致总是好的——至少对自己。如果可能的话,对别人也是如此。
### 事件对象的额外属性
@@ -386,344 +384,6 @@ form.addEventListener("submit", (e) => {
> **备注:** 你可以在 GitHub 上查看这个示例的完整源代码 [preventdefault-validation.html](https://github.com/mdn/learning-area/blob/main/javascript/building-blocks/events/preventdefault-validation.html),也可以[在线运行它](https://mdn.github.io/learning-area/javascript/building-blocks/events/preventdefault-validation.html)。
-## 事件冒泡
-
-事件冒泡描述了浏览器如何处理针对嵌套元素的事件。
-
-### 在父元素上设置监听器
-
-考虑像这样的网页:
-
-```html
-
- 点我!
-
-
-```
-
-这里有一个在其他元素({{HTMLElement("div")}})内部的按钮,可以说这里的 `` 元素是其中包含元素的**父元素**。当我们在父元素附加单击事件处理器,并点击按钮时,会发生什么?
-
-```js
-const output = document.querySelector("#output");
-function handleClick(e) {
- output.textContent += `你在 ${e.currentTarget.tagName} 元素上进行了点击\n`;
-}
-
-const container = document.querySelector("#container");
-container.addEventListener("click", handleClick);
-```
-
-{{ EmbedLiveSample('在父元素上设置监听器', '100%', 200, "", "") }}
-
-你会发现在用户单击按钮时,父元素上触发了单击事件:
-
-```
-你在 DIV 元素上进行了点击
-```
-
-这是有道理的:按钮在 `
` 里面,所以当你点击按钮的时候,你也隐含地点击了它所在的元素。
-
-### 冒泡示例
-
-如果在按钮*及*其父元素上同时添加事件处理器,会发生什么?
-
-```html
-
-
- 点我!
-
-
-
-```
-
-让我们试着给按钮、它的父元素(`
`)以及包含它们的 {{HTMLElement("body")}} 元素添加点击事件处理器:
-
-```js
-const output = document.querySelector("#output");
-function handleClick(e) {
- output.textContent += `你在 ${e.currentTarget.tagName} 元素上进行了点击\n`;
-}
-
-const container = document.querySelector("#container");
-const button = document.querySelector("button");
-
-document.body.addEventListener("click", handleClick);
-container.addEventListener("click", handleClick);
-button.addEventListener("click", handleClick);
-```
-
-{{ EmbedLiveSample('冒泡', '100%', 200, "", "") }}
-
-你会发现在用户单击按钮时,所有三个元素都触发了单击事件:
-
-```
-你在 BUTTON 元素上进行了点击
-你在 DIV 元素上进行了点击
-你在 BODY 元素上进行了点击
-```
-
-在这种情况下:
-
-- 最先触发按钮上的单击事件
-- 然后是按钮的父元素(`
` 元素)
-- 然后是 `
` 的父元素(`` 元素)
-
-我们可以这样描述:事件从被点击的最里面的元素**冒泡**而出。
-
-这种行为可能是有用的,也可能引起意想不到的问题。在接下来的章节中,我们将看到它引起的一个问题,并找到解决方案。
-
-### 视频播放器示例
-
-在这个示例中,我们的页面包含一个视频,最初它为隐藏状态;还有一个标记为“显示视频”的按钮。我们希望有如下交互:
-
-- 当用户单击“显示视频”按钮时,显示包含视频的盒子,但不要开始播放视频。
-- 当用户在视频上单击时,开始播放视频。
-- 当用户单击盒子内视频以外的任何区域时,隐藏盒子。
-
-HTML 代码看起来像这样:
-
-```html
-
显示视频
-
-
-
-
-
- 你的浏览器不支持 HTML 视频,这里有视频的替代链接 。
-
-
-
-```
-
-它包含:
-
-- 一个 `
` 元素
-- 一个 `` 元素,最初其包含 `class="hidden"` 属性
-- 一个嵌套在 `
` 元素中的 `
` 元素
-
-我们使用 CSS 来隐藏具有 `"hidden"` 类的元素。
-
-```css hidden
-div {
- width: 100%;
- height: 100%;
- background-color: #eee;
-}
-
-.hidden {
- display: none;
-}
-
-div video {
- padding: 40px;
- display: block;
- width: 400px;
- margin: 40px auto;
-}
-```
-
-JavaScript 代码看起来像这样:
-
-```js
-const btn = document.querySelector("button");
-const box = document.querySelector("div");
-const video = document.querySelector("video");
-
-btn.addEventListener("click", () => box.classList.remove("hidden"));
-video.addEventListener("click", () => video.play());
-box.addEventListener("click", () => box.classList.add("hidden"));
-```
-
-它添加了三个 `'click'` 事件处理器:
-
-- 一个在 `` 上,它显示了包含 `` 的 ``
-- 一个在 `
` 上,用于开始播放视频
-- 一个在 `` 上,用于隐藏视频
-
-让我们看看这个如何工作:
-
-{{ EmbedLiveSample('视频播放器示例', '100%', 500) }}
-
-你应该看到,当你点击按钮时,盒子和它所包含的视频都显示出来。但当你点击视频时,视频开始播放,但盒子又被隐藏起来了!
-
-视频在 `
` 内(是它的一部分),所以点击视频会*同时*运行两个事件处理器,导致这种行为。
-
-### 使用 stopPropagation() 修复问题
-
-正如我们在上一节所看到的,事件冒泡有时会产生问题,但有一种方法可以防止这些问题。[`Event`](/zh-CN/docs/Web/API/Event) 对象有一个可用的函数,叫做 [`stopPropagation()`](/zh-CN/docs/Web/API/Event/stopPropagation),当在一个事件处理器中调用时,可以防止事件向任何其他元素传递。
-
-我们可以通过修改 JavaScript 代码来修复当前的问题:
-
-```js
-const btn = document.querySelector("button");
-const box = document.querySelector("div");
-const video = document.querySelector("video");
-
-btn.addEventListener("click", () => box.classList.remove("hidden"));
-
-video.addEventListener("click", (event) => {
- event.stopPropagation();
- video.play();
-});
-
-box.addEventListener("click", () => box.classList.add("hidden"));
-```
-
-我们在这里所做的是在 `
` 元素的 `'click'` 事件的处理器中对事件对象调用 `stopPropagation()`。这将阻止该事件向盒子内传递。现在试着点击按钮,然后再点击视频:
-
-{{EmbedLiveSample("使用 stopPropagation() 修复问题", '100%', 500)}}
-
-```html hidden
-显示视频
-
-
-
-
-
- 你的浏览器不支持 HTML 视频,这里有视频的替代链接 。
-
-
-
-```
-
-```css hidden
-div {
- width: 100%;
- height: 100%;
- background-color: #eee;
-}
-
-.hidden {
- display: none;
-}
-
-div video {
- padding: 40px;
- display: block;
- width: 400px;
- margin: 40px auto;
-}
-```
-
-### 事件捕获
-
-事件传播的另一种形式是*事件捕获*。这就像事件冒泡,但顺序是相反的:事件不是先在最内层的目标元素上发生,然后在连续较少的嵌套元素上发生,而是先在*最小嵌套*元素上发生,然后在连续更多的嵌套元素上发生,直到达到目标。
-
-事件捕获默认是禁用的,你需要在 `addEventListener()` 的 `capture` 选项中启用它。
-
-以下示例类似于之前看到的[冒泡示例](#冒泡示例),除了使用了 `capture` 选项以外:
-
-```html
-
-
- 点我!
-
-
-
-```
-
-```js
-const output = document.querySelector("#output");
-function handleClick(e) {
- output.textContent += `你在 ${e.currentTarget.tagName} 元素上进行了点击\n`;
-}
-
-const container = document.querySelector("#container");
-const button = document.querySelector("button");
-
-document.body.addEventListener("click", handleClick, { capture: true });
-container.addEventListener("click", handleClick, { capture: true });
-button.addEventListener("click", handleClick);
-```
-
-{{ EmbedLiveSample('事件捕获', '100%', 200, "", "") }}
-
-在这种情况下,消息出现的顺序发生了颠倒:`` 事件处理器首先触发,然后是 `` 的,最后是 `
` 的:
-
-```
-你在 BODY 元素上进行了点击
-你在 DIV 元素上进行了点击
-你在 BUTTON 元素上进行了点击
-```
-
-为什么要同时使用捕获和冒泡功能?在过去的坏日子里,当浏览器的交叉兼容性远不如现在时,Netscape 只使用事件捕捉,而 Internet Explorer 只使用事件冒泡。当 W3C 决定尝试将行为标准化并达成共识时,他们最终确定了这个包括这两种行为的系统,这也是现代浏览器所实现的。
-
-默认情况下,几乎所有的事件处理程序都是在冒泡阶段注册的,这在大多数情况下更有意义。
-
-## 事件委托
-
-在上一节中,我们看了一个由事件冒泡引起的问题以及如何解决它。不过,事件冒泡并不只是令人讨厌:它可以非常有用。特别是,它可以实现**事件委托**。在这种做法中,当我们想在用户与大量的子元素中的任何一个互动时运行一些代码时,我们在它们的父元素上设置事件监听器,让发生在它们身上的事件冒泡到它们的父元素上,而不必在每个子元素上单独设置事件监听器。
-
-让我们回到第一个例子,当用户点击一个按钮时,我们设置整个页面的背景颜色。假设取而代之的是,页面被分为 16 个区域,我们想在用户点击每个区域时将其设置为随机颜色。
-
-这里是 HTML 代码:
-
-```html
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-我们有一些 CSS 代码,来设置每一个区域的尺寸和位置:
-
-```css
-.tile {
- height: 100px;
- width: 25%;
- float: left;
-}
-```
-
-在 JavaScript 代码中,我们向每一个区域中添加单击事件处理器。但是,一个更简单、更有效的选择是在父节点上设置点击事件处理器,并依靠事件冒泡来确保用户点击每个区域时处理程序被执行:
-
-```js
-function random(number) {
- return Math.floor(Math.random() * number);
-}
-
-function bgChange() {
- const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;
- return rndCol;
-}
-
-const container = document.querySelector("#container");
-
-container.addEventListener("click", (event) => {
- event.target.style.backgroundColor = bgChange();
-});
-```
-
-示例输出如下(试着随便点击):
-
-{{ EmbedLiveSample('事件委托', '100%', 430, "", "") }}
-
-> **备注:** 在这个例子中,我们使用 `event.target` 来获取事件的目标元素(也就是最里面的元素)。如果我们想访问处理这个事件的元素(在这个例子中是容器),我们可以使用 `event.currentTarget`。
-
-> **备注:** 完整的源代码见 [useful-eventtarget.html](https://github.com/mdn/learning-area/blob/main/javascript/building-blocks/events/useful-eventtarget.html);也可以在这里[在线运行它](https://mdn.github.io/learning-area/javascript/building-blocks/events/useful-eventtarget.html)。
-
## 并不只是网页
事件不是 JavaScript 独有的——大多数编程语言都有某种事件模型,而模型的工作方式往往与 JavaScript 的方式不同。事实上,网页的 JavaScript 的事件模型与其他环境中使用的 JavaScript 的事件模型也是不同的。
@@ -734,23 +394,10 @@ container.addEventListener("click", (event) => {
在这个学习阶段,你不需要了解其他此类环境的情况;我们只是想让你明白,在不同的编程环境中,事件会有所不同。
-## 技能测试!
-
-你已经到了本文的结尾,但你能记住最重要的信息吗?在你继续前进之前,要验证你是否记住了这些信息,请前往[技能测试:事件](/zh-CN/docs/Learn/JavaScript/Building_blocks/Test_your_skills:_Events)页面进行测试。
-
## 结论
现在你应该知道在这个早期阶段需要了解的所有 web 事件。如上所述,事件并不是 JavaScript 的核心部分——它们是在浏览器 Web API 中定义的。
另外,理解 JavaScript 在不同环境下使用不同的事件模型很重要——从 Web API 到其他领域,如浏览器 WebExtensions 和 Node.js(服务器端 JavaScript)。我们并不期望现在了解所有这些领域,但是当你在学习 web 开发的过程中,理解这些事件的基础是很有帮助的。
-如果你有什么不明白的地方,请重新阅读这篇文章,或者[联系我们](https://discourse.mozilla.org/c/mdn/learn/250)寻求帮助。
-
-## 参见
-
-- [domevents.dev](https://domevents.dev/)——一个非常有用的交互式游乐场应用程序,能够通过探索来学习 DOM 事件系统的行为。
-- [事件参考](/zh-CN/docs/Web/Events)
-- [Event order](https://www.quirksmode.org/js/events_order.html)(探讨了捕获和冒泡)——由 Peter-Paul Koch 撰写的非常详尽的文章。
-- [Event accessing](https://www.quirksmode.org/js/events_access.html)(探讨了事件对象)——另外一篇由 Peter-Paul Koch 撰写的非常详尽的文章。
-
-{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}
+{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Event_bubbling", "Learn/JavaScript/Building_blocks")}}
From b9b492222a20f71035c558b3d1c5e5bbec61d433 Mon Sep 17 00:00:00 2001
From: Jason Ren <40999116+jasonren0403@users.noreply.github.com>
Date: Tue, 2 Jul 2024 08:01:02 +0000
Subject: [PATCH 4/5] resolve more links
---
files/zh-cn/learn/javascript/howto/index.md | 4 ++--
files/zh-cn/web/api/event/bubbles/index.md | 2 +-
files/zh-cn/web/api/event/currenttarget/index.md | 5 ++---
files/zh-cn/web/api/event/index.md | 5 +++--
files/zh-cn/web/api/event/originaltarget/index.md | 14 +++++---------
files/zh-cn/web/api/event/target/index.md | 12 +-----------
.../web/api/mouseevent/relatedtarget/index.md | 1 -
7 files changed, 14 insertions(+), 29 deletions(-)
diff --git a/files/zh-cn/learn/javascript/howto/index.md b/files/zh-cn/learn/javascript/howto/index.md
index ef8d4b21ab5343..0d0f8664397aac 100644
--- a/files/zh-cn/learn/javascript/howto/index.md
+++ b/files/zh-cn/learn/javascript/howto/index.md
@@ -196,8 +196,8 @@ const myObject = {
- [我该使用什么样的机制将事件代码添加到我的网页上?](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events#我该使用哪种机制?)
- [什么是事件对象,如何使用它?](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events#事件对象)
- [如何防止默认事件行为?](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events#阻止默认行为)
-- [事件如何在嵌套元素中触发?(事件传递及其相关内容——事件冒泡及捕获)](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events#事件冒泡及捕获)
-- [什么是事件委托,它如何工作?](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events#事件委托)
+- [事件如何在嵌套元素中触发?(事件传递及其相关内容——事件冒泡及捕获)](/zh-CN/docs/Learn/JavaScript/Building_blocks/Event_bubbling)
+- [什么是事件委托,它如何工作?](/zh-CN/docs/Learn/JavaScript/Building_blocks/Event_bubbling#事件委托)
### 面向对象的 JavaScript
diff --git a/files/zh-cn/web/api/event/bubbles/index.md b/files/zh-cn/web/api/event/bubbles/index.md
index 7c4b2136a35af7..1ebd371275b12e 100644
--- a/files/zh-cn/web/api/event/bubbles/index.md
+++ b/files/zh-cn/web/api/event/bubbles/index.md
@@ -9,7 +9,7 @@ l10n:
{{domxref("Event")}} 接口的 **`bubbles`** 只读属性表明事件是否会沿 DOM 树向上冒泡。
-> **备注:** 有关冒泡的更多信息,请参阅[事件冒泡和捕获](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events#事件冒泡)。
+> **备注:** 有关冒泡的更多信息,请参阅[事件冒泡](/zh-CN/docs/Learn/JavaScript/Building_blocks/Event_bubbling)。
## 值
diff --git a/files/zh-cn/web/api/event/currenttarget/index.md b/files/zh-cn/web/api/event/currenttarget/index.md
index fa815622a010cb..a615e591ca8dfc 100644
--- a/files/zh-cn/web/api/event/currenttarget/index.md
+++ b/files/zh-cn/web/api/event/currenttarget/index.md
@@ -9,7 +9,7 @@ l10n:
{{domxref("Event")}} 接口的 **`currentTarget`** 只读属性用于标识事件处理器所附加的元素。
-这并不总是与触发事件的元素相同,因为事件可能在具有处理器的元素的后代上触发,然后通过事件[冒泡](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events#事件冒泡)到具有处理器的元素。事件的触发元素由 {{domxref("Event.target")}} 给出。
+这并不总是与触发事件的元素相同,因为事件可能在具有处理器的元素的后代上触发,然后通过事件[冒泡](/zh-CN/docs/Learn/JavaScript/Building_blocks/Event_bubbling)到具有处理器的元素。事件的触发元素由 {{domxref("Event.target")}} 给出。
请注意,`currentTarget` 的值仅在事件处理器中可用。在事件处理器外部,它将为 `null`。这意味着,例如,如果在事件处理器内部获得 `Event` 对象的引用然后在事件处理器外部访问其 `currentTarget` 属性,则其值将为 `null`。
@@ -88,5 +88,4 @@ reset.addEventListener("click", () => document.location.reload());
## 参见
-- [事件目标的比较](/zh-CN/docs/Web/API/Event/Comparison_of_Event_Targets)
-- [事件冒泡](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events#事件冒泡)
+- [事件冒泡](/zh-CN/docs/Learn/JavaScript/Building_blocks/Event_bubbling)
diff --git a/files/zh-cn/web/api/event/index.md b/files/zh-cn/web/api/event/index.md
index e52cdf2cb44d6e..ebd75f4924e19f 100644
--- a/files/zh-cn/web/api/event/index.md
+++ b/files/zh-cn/web/api/event/index.md
@@ -17,7 +17,7 @@ l10n:
> **备注:** 一个元素可以绑定多个事件处理器,甚至是对于完全相同的事件。尤其是相互独立的代码模块出于不同的目的附加事件处理器。(比如,一个网页同时有着广告模块和统计模块同时监听视频播放。)
-当有很多嵌套的元素,每个元素都有着自己的事件处理器,事件处理过程会变得非常复杂。尤其当一个父元素和子元素绑定完全相同的事件时,因为结构上的重叠,事件在技术层面发生在两个元素中,触发的顺序取决于每个处理器的[事件冒泡和事件捕获](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events#事件冒泡及捕获)的设置。
+当有很多嵌套的元素,每个元素都有着自己的事件处理器,事件处理过程会变得非常复杂。尤其当一个父元素和子元素绑定完全相同的事件时,因为结构上的重叠,事件在技术层面发生在两个元素中,触发的顺序取决于每个处理器的[事件冒泡](/zh-CN/docs/Learn/JavaScript/Building_blocks/Event_bubbling)的设置。
## 基于 Event 的接口
@@ -138,5 +138,6 @@ l10n:
## 参见
- 可用的事件类型:[Event 参考](/zh-CN/docs/Web/Events)
-- [Event 目标的比较](/zh-CN/docs/Web/API/Event/Comparison_of_Event_Targets)(目标 `target` vs 当前目标 `currentTarget` vs 相关目标 `relatedTarget` vs 初始目标 `originalTarget`)
+- [事件介绍](/zh-CN/docs/Learn/JavaScript/Building_blocks/Events)
+- [事件冒泡](/zh-CN/docs/Learn/JavaScript/Building_blocks/Event_bubbling)
- [创建和触发自定义事件](/zh-CN/docs/Web/Events/Creating_and_triggering_events)
diff --git a/files/zh-cn/web/api/event/originaltarget/index.md b/files/zh-cn/web/api/event/originaltarget/index.md
index 65dc09eee131b5..9dbc9f0bd1b419 100644
--- a/files/zh-cn/web/api/event/originaltarget/index.md
+++ b/files/zh-cn/web/api/event/originaltarget/index.md
@@ -1,21 +1,17 @@
---
-title: Event.originalTarget
+title: Event:originalTarget 属性
slug: Web/API/Event/originalTarget
+l10n:
+ sourceCommit: c20c12fab32381b983b4148d712fda227d34e2bd
---
{{ ApiRef("DOM") }} {{Non-standard_header}}
-**`originalTarget`** 只读属性是事件重定向之前的原始目标。(Mozilla-特有)
-
-在 XBL 的匿名内容中,这将是该事件最初触发的匿名节点。看到匿名的内容。查看[Anonymous Content#Event_Flow_and_Targeting](/zh-CN/docs/XBL/XBL_1.0_Reference/Anonymous_Content#Event_Flow_and_Targeting) 获取更多细节。
-
-注意:原始目标也可能是原生的匿名内容,在这种情况下,它对于非特权代码是无用的。
-
-参见[事件目标对比](/zh-CN/docs/Web/API/Event/Comparison_of_Event_Targets)。
+**`originalTarget`** 只读属性是事件重定向之前的原始目标。与 {{domxref("Event.explicitOriginalTarget")}} 不同,原始目标也可能是原生的匿名内容。
## 规范
-这是一个 Mozilla 特有的属性,不属于任何规范。它不会成为标准。
+*这是一个 Mozilla 特有的属性,不属于任何规范。它不会成为标准。*
## 浏览器兼容性
diff --git a/files/zh-cn/web/api/event/target/index.md b/files/zh-cn/web/api/event/target/index.md
index ddf24327fe940c..508df3402f9b7b 100644
--- a/files/zh-cn/web/api/event/target/index.md
+++ b/files/zh-cn/web/api/event/target/index.md
@@ -43,17 +43,7 @@ ul.addEventListener("click", hide, false);
{{Compat}}
-在 IE6-8 中,事件模型与标准不同。使用非标准的 [`element.attachEvent()`](http://msdn.microsoft.com/en-us/library/ie/ms536343%28v=vs.85%29.aspx) 方法绑定事件监听器。在该模型中,事件对象有一个 `srcElement` 属性,等价于`target` 属性。
-
-```js
-function hide(e) {
- // 支持 IE6-8
- var target = e.target || e.srcElement;
- target.style.visibility = "hidden";
-}
-```
-
## 参见
-- [Comparison of Event Targets](/zh-CN/DOM/event/Comparison_of_Event_Targets)
+- [事件冒泡](/zh-CN/docs/Learn/JavaScript/Building_blocks/Event_bubbling)
- {{domxref("Event.currentTarget")}}
diff --git a/files/zh-cn/web/api/mouseevent/relatedtarget/index.md b/files/zh-cn/web/api/mouseevent/relatedtarget/index.md
index eaacee52c71ce5..d3f832716bd6e9 100644
--- a/files/zh-cn/web/api/mouseevent/relatedtarget/index.md
+++ b/files/zh-cn/web/api/mouseevent/relatedtarget/index.md
@@ -110,4 +110,3 @@ function overListener(event) {
## 参见
- {{ domxref("MouseEvent") }}
-- [Comparison of Event Targets](/zh-CN/docs/DOM/event/Comparison_of_Event_Targets)
From 2337f32209d41aab18275b81512964496cbd7db2 Mon Sep 17 00:00:00 2001
From: Jason Ren <40999116+jasonren0403@users.noreply.github.com>
Date: Tue, 2 Jul 2024 16:04:07 +0800
Subject: [PATCH 5/5] Apply suggestions from code review
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
files/zh-cn/web/api/event/originaltarget/index.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/files/zh-cn/web/api/event/originaltarget/index.md b/files/zh-cn/web/api/event/originaltarget/index.md
index 9dbc9f0bd1b419..9d965eede88240 100644
--- a/files/zh-cn/web/api/event/originaltarget/index.md
+++ b/files/zh-cn/web/api/event/originaltarget/index.md
@@ -11,7 +11,7 @@ l10n:
## 规范
-*这是一个 Mozilla 特有的属性,不属于任何规范。它不会成为标准。*
+_这是一个 Mozilla 特有的属性,不属于任何规范。它不会成为标准。_
## 浏览器兼容性