recursal/MDN huggingface dataset:
创建和触发事件
=======

本文演示了如何创建和分派 DOM 事件。这些事件通常称为**合成事件**，而不是浏览器本身触发的事件。

创建自定义事件
-------

可以使用 `Event` 构造函数创建事件，如下所示：


```js
const event = new Event("build");

// 监听该事件。
elem.addEventListener(
  "build",
  (e) => {
    /\* … \*/
  },
  false,
);

// 分派该事件。
elem.dispatchEvent(event);
```


上述代码使用了 EventTarget.dispatchEvent() 方法。

绝大多数现代浏览器中都支持这个构造函数。要了解更为复杂的方法，可参考下面的过时的方式。

### 添加自定义数据——CustomEvent()

 要向事件对象添加更多数据，可以使用 CustomEvent 接口，**detail** 属性可用于传递自定义数据。
 例如，可以像这样创建事件：


```js
const event = new CustomEvent("build", { detail: elem.dataset.time });
```


下面的代码允许你在事件监听器中访问更多的数据：


```js
function eventHandler(e) {
  console.log(`The time is: ${e.detail}`);
}
```

### 过时的方式

早期的创建事件的方法使用了受 Java 启发的 API。下面是一个使用 `document.createEvent()` 的示例：


```js
// 创建事件。
const event = document.createEvent("Event");

// 定义事件的名称为“build”。
event.initEvent("build", true, true);

// 监听该事件。
elem.addEventListener(
  "build",
  (e) => {
    // e.target 与 elem 相匹配
  },
  false,
);

// 目标（target）可以是任何元素或其他 EventTarget。
elem.dispatchEvent(event);
```

### 事件冒泡

通常需要从子元素触发事件，并让其祖先捕获它；且可以带有数据：


```html
<form>
  <textarea></textarea>
</form>
```



```js
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");

// 创建一个新事件，允许冒泡，并提供要传递给“detail”属性的任何数据
const eventAwesome = new CustomEvent("awesome", {
  bubbles: true,
  detail: { text: () => textarea.value },
});

// 表单（form）元素监听自定义的“awesome”事件，然后在控制台打印传递的 text() 方法的输出
form.addEventListener("awesome", (e) => console.log(e.detail.text()));

// 当用户输入时，表单中的文本区域会分派/触发事件，并以自身为事件的起点
textarea.addEventListener("input", (e) => e.target.dispatchEvent(eventAwesome));
```

### 动态创建和分派事件

元素可以监听尚未创建的事件：


```html
<form>
  <textarea></textarea>
</form>
```



```js
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");

form.addEventListener("awesome", (e) => console.log(e.detail.text()));

textarea.addEventListener("input", function () {
  // 动态创建并分派/触发一个事件
  // 注意：我们还可以使用“函数表达式”（而不是“箭头函数表达式”），这样“this”将表示该元素
  this.dispatchEvent(
    new CustomEvent("awesome", {
      bubbles: true,
      detail: { text: () => textarea.value },
    }),
  );
});
```

触发内置事件
------

下面的示例演示了使用 DOM 方法在复选框上模拟点击（click）（即，通过编程方法生成 click 事件）。参见这个动态示例。


```js
function simulateClick() {
  const event = new MouseEvent("click", {
    view: window,
    bubbles: true,
    cancelable: true,
  });
  const cb = document.getElementById("checkbox");
  const cancelled = !cb.dispatchEvent(event);

  if (cancelled) {
    // 处理器调用了 preventDefault。
    alert("cancelled");
  } else {
    // 没有处理器调用 preventDefault。
    alert("not cancelled");
  }
}
```

参见
--

* CustomEvent()
* `document.createEvent()`
* `Event.initEvent()`
* `EventTarget.dispatchEvent()`
* `EventTarget.addEventListener()`
ARIA
====

无障碍富互联网应用（Accessible Rich Internet Applications，**ARIA**）是一组角色和属性，用于定义使残障人士更易于访问 web 内容和 web 应用程序（尤其是使用 JavaScript 开发的应用程序）的方法。

它补充了 HTML，以便在没有其他机制时可以将应用程序中常用的交互和小部件传递给辅助技术。例如，ARIA 支持无障碍 JavaScript 小部件、表单提示和错误消息、实时内容更新等。

**警告：** 许多这些小部件在现代浏览器中都已经完全支持。如果有正确语义的 HTML 元素存在的话，**开发人员应该更喜欢使用这样的元素而不是使用 ARIA**。例如，原生元素具有内置的键盘无障碍、角色和状态。但是，如果你选择使用 ARIA，则你有责任在脚本中模仿等效的浏览器行为。

使用 ARIA 的第一规则是“如果你能够使用原生的 HTML 元素或属性，并且有你需要但已经建立在里面的语义和行为，而不是重新调整元素的用途并添加 ARIA 角色、状态或者属性来使它更加无障碍，那么你就应该如此。”

**备注：** 有个说法叫做“ARIA 宁缺毋滥”。在 WebAim 对超过 100 万个主页的调查中，他们发现，有 ARIA 存在的主页比那些没有 ARIA 的，多检测出了平均 41% 的错误。尽管 ARIA 是为了使网页更加无障碍而设计的，但是如果使用不当，可能适得其反。

这是进度条小部件的标记：


```html
<div
 id="percent-loaded"
 role="progressbar"
 aria-valuenow="75"
 aria-valuemin="0"
 aria-valuemax="100"></div>
```


这个进度条是使用 `<div>` 构建的，没有任何意义。我们加入 ARIA 角色和属性以添加意义。在这个例子中，`role="progressbar"` (en-US) 属性告知浏览器，这个元素实际上是一个由 JavaScript 驱动的进度条小部件。`aria-valuemin` (en-US) 和 `aria-valuemax` (en-US) 属性指定进度条的最小值和最大值，`aria-valuenow` (en-US) 描述进度条的当前状态，因此必须使用 JavaScript 保持更新。

除了将它们直接放置在元素中之外，还可以将 ARIA 属性添加到元素中，并使用 JavaScript 代码动态更新，如下所示：


```js
// 在 DOM 中，寻找进度条 <div>。
var progressBar = document.getElementById("percent-loaded");

// 设置其 ARIA 属性和状态，
// 这样辅助技术知道它是哪一种部件。
progressBar.setAttribute("role", "progressbar");
progressBar.setAttribute("aria-valuemin", 0);
progressBar.setAttribute("aria-valuemax", 100);

// 创建可以在任何时候调用的函数，
// 以更新进度条的值。
function updateProgress(percentComplete) {
  progressBar.setAttribute("aria-valuenow", percentComplete);
}
```


所有对非辅助技术的可用的内容都应该对辅助技术可用。类似地，不应包含针对辅助技术用户使用但对于不使用辅助技术的用户无法访问的任何特性。这个进度条需要有相应的样式，从而看起来像进度条。

如果使用原生的 `<progress>` 元素，则会简单得多：


```html
<progress id="percent-loaded" value="75" max="100">75 %</progress>
```


**备注：** `<progress>` 元素不允许 `min` 属性，最小值永远为 0。

**备注：** HTML 地标元素（`<main>`、`<header>`、`<nav>` 等）具有内置的 ARIA 角色，因此有无需复制它们。

支持
--

与任何其他 Web 技术一样，ARIA 也有不同程度的支持。支持基于所使用的操作系统和浏览器，以及与之交互的辅助技术类型。此外，操作系统、浏览器和辅助技术的版本也是影响因素。较旧的软件版本可能不支持某些 ARIA 角色、仅部分支持或误报其功能。

同样重要的是要承认一些依赖辅助技术的人不愿意升级他们的软件，因为害怕失去与他们的计算机和浏览器交互的能力。因此，尽可能使用语义化的 HTML 元素很重要，因为语义 HTML 对辅助技术的支持要好得多。

使用实际辅助技术测试你编写的 ARIA 也很重要。就像浏览器模拟器和模拟器不是测试完全支持的有效解决方案一样，代理辅助技术解决方案不足以完全保证功能。

参考
--

ARIA 角色

包含了 MDN 中讨论的所有 WAI-ARIA 角色的参考页面。

ARIA 状态和属性

包含了 MDN 中讨论的所有 WAI-ARIA 状态和属性的参考页面。

标准化工作
-----

WAI-ARIA 规范

W3C 规范本身。

WAI-ARIA 创作实践

官方最佳实践记录了如何最好地对常见小部件和交互进行 ARIA 化。一个很好的资源。

脚本小部件的 ARIA
-----------

编写可通过键盘导航的 JavaScript 小部件

`<input>`、`<button>` 等内置元素具有内置键盘辅助功能。如果你使用 `<div>` 和 ARIA 来“伪造”这些，则必须确保你的小部件可通过键盘访问。

实时区域

实时区域向屏幕阅读器提供有关如何处理页面内容更改的建议。

视频
--

以下演讲是了解 ARIA 的好方法：

ARIA, Accessibility APIs and coding like you give a damn! – Léonie Watson
移动无障碍清单
=======

该文档为移动应用开发者提供一个无障碍需求的简要清单。此文档将随着技术模式的发展而不断演进。

颜色
--

* 颜色对比度**必须**遵循 WCAG 2.0 AA 等级需求：
    + 普通文本的对比率为 4.5:1（小于 18 磅或黑体 14 磅）
    + 大文本对比率为 3:1（大于等于 18 磅或黑体 14 磅）【译者注：字体单位为 point、PT】
* 颜色传递的信息，**必须**也通过其他方式标明（例如，链接文本中的下划线）

**备注：** Jon Snook 开发的 颜色对比度检查器 - Colour Contrast Checker 可以轻松检查前景和背景的对比度。同样，Tanaguru Contrast-Finder 这个工具能做类似的检查，并且会推荐你考虑使用类似的更好的对比度

可视化
---

* **不**使用用于隐藏内容的技巧处理视觉效果，例如，不透明度为零，z-index 规则，离屏位置。
* 当前可见的屏幕之外的内容，**必须**是不可见的。（特别是单一页面应用中包含多个卡片选项）:
    + **使用** `hidden` 特性或 `visibility` 或 `display` 样式属性。
    + 除非不可避免，**不应该**使用 `aria-hidden` 特性。
焦点
--

* 所有可激活元素**必须**可被聚焦：
    + 标准控件，如链接、按钮、表单域默认可被聚焦。
    + 非标准控件**必须**分配给它们一个适当的 ARIA Role 如 `button`，`link` 或者 `checkbox`。
* 焦点应该是有逻辑顺序，且方式一致。
文本等效
----

* 应用中，每个展示的非文本元素都**必须**提供等效文本。
    + 恰当的位置使用 *alt* 和 *title*（请参考 Steve Faulkner 的帖子 - 关于 Using the HTML title attribute 。）
    + 如果上面的特性不适用，使用恰当的ARIA Properties，比如 `aria-label`, `aria-labelledby`, 或 `aria-describedby`.
* **必须**避免文本图像。
* 所有的表单控件**必须**有标签 (`<label>` elements) ，以便于读屏用户的使用。
状态处理
----

* 标准控件，如单选按钮和复选是通过操作系统处理的，而其他自定义控件的状态改变需要通过 ARIA States ，如 `aria-checked`, `aria-disabled`, `aria-selected`, `aria-expanded`,和 `aria-pressed`.
General Guidelines 常规指南
-----------------------

* 应用必须提供标题。【译者注：此处的标题为 title】
* 标题**不能**破坏层次结构。【译者注：此处的标题为 headings】

```html
<h1>Top level heading</h1>
<h2>Secondary heading</h2>
<h2>Another secondary heading</h2>
<h3>Low level heading</h3>
```

* 应使用 ARIA Landmark Roles 描述应用或文档的结构，如 `banner`, `complementary`, `contentinfo`, `main`, `navigation`, `search`.
* 触摸事件处理器，只能通过 `touchend` 事件触发。
* 触摸目标必须足够大，方便用户交互 (参考 BBC Mobile Accessibility Guidelines 关于触摸目标尺寸的指南)

**备注：** Tanaguru's automated accessibility testing service 提供一个有效的方法，排查网页上的，或者是可安装的 Web 应用中无障碍问题（如，Firefox OS）。tanaguru.org，你可以参与该项目或者发现更多技术实现。

**备注：** The 该文档的最初版本 - original version of this document 是由 Yura Zenevich 完成。
ARIA 状态及属性
==========

这个页面列出了 MDN 上讨论的所有 WAI-ARIA 属性的参考页面。

ARIA 属性用于修改无障碍树中定义的元素的状态和属性。

**备注：** ARIA 仅用于修改无障碍树，进而改变辅助技术向用户呈现内容的方式。ARIA 不会改变元素的功能或行为。当使用非语义化的 HTML 元素来实现其他功能时，你必须使用 JavaScript 来控制元素的实际行为、焦点以及 ARIA 状态。

ARIA 特性类别
---------

ARIA 的状态和属性（合称为“特性”）共有 4 类：

1. ### 小部件（widget）特性

    * `aria-autocomplete` (en-US)
    * `aria-checked` (en-US)
    * `aria-disabled` (en-US)
    * `aria-errormessage` (en-US)
    * `aria-expanded` (en-US)
    * `aria-haspopup` (en-US)
    * `aria-hidden`
    * `aria-invalid` (en-US)
    * `aria-label`
    * `aria-level` (en-US)
    * `aria-modal` (en-US)
    * `aria-multiline` (en-US)
    * `aria-multiselectable` (en-US)
    * `aria-orientation` (en-US)
    * `aria-placeholder` (en-US)
    * `aria-pressed` (en-US)
    * `aria-readonly` (en-US)
    * `aria-required` (en-US)
    * `aria-selected` (en-US)
    * `aria-sort` (en-US)
    * `aria-valuemax` (en-US)
    * `aria-valuemin` (en-US)
    * `aria-valuenow` (en-US)
    * `aria-valuetext` (en-US)
2. ### 活动区域特性

    * `aria-busy` (en-US)
    * `aria-live` (en-US)
    * `aria-relevant` (en-US)
    * `aria-atomic` (en-US)
3. ### 拖放特性

    * `aria-dropeffect` (en-US)
    * `aria-grabbed` (en-US)
4. ### 关系特性

    * `aria-activedescendant` (en-US)
    * `aria-colcount` (en-US)
    * `aria-colindex` (en-US)
    * `aria-colspan` (en-US)
    * `aria-controls` (en-US)
    * `aria-describedby` (en-US)
    * `aria-description` (en-US)
    * `aria-details` (en-US)
    * `aria-errormessage` (en-US)
    * `aria-flowto` (en-US)
    * `aria-labelledby`
    * `aria-owns` (en-US)
    * `aria-posinset` (en-US)
    * `aria-rowcount` (en-US)
    * `aria-rowindex` (en-US)
    * `aria-rowspan` (en-US)
    * `aria-setsize` (en-US)
全局 ARIA 特性
----------

无论是否应用了 ARIA 角色，某些状态和属性始终适用于所有的 HTML 元素。它们被定义为“全局”特性。所有角色和基本标记元素都支持全局状态和属性。

上面所列出的许多特性都是全局的，这意味着除非被“特别禁止”，它们可以被包含在任意的元素中：

* `aria-atomic` (en-US)
* `aria-busy` (en-US)
* `aria-controls` (en-US)
* `aria-current` (en-US)
* `aria-describedby` (en-US)
* `aria-description` (en-US)
* `aria-details` (en-US)
* `aria-disabled` (en-US)
* `aria-dropeffect` (en-US)
* `aria-errormessage` (en-US)
* `aria-flowto` (en-US)
* `aria-grabbed` (en-US)
* `aria-haspopup` (en-US)
* `aria-hidden`
* `aria-invalid` (en-US)
* `aria-keyshortcuts` (en-US)
* `aria-label`
* `aria-labelledby`
* `aria-live` (en-US)
* `aria-owns` (en-US)
* `aria-relevant` (en-US)
* `aria-roledescription` (en-US)

除了 `aria-label` 和 `aria-labelledby` 这两个被“特别禁止”的属性，其他属性是全局适用的。这两个被“特别禁止”的属性无法在具有 `presentation` (en-US) 角色或与其同义的 `none` (en-US) 角色的元素上使用。

MDN 上介绍的状态和属性
-------------

以下是 MDN 上介绍的 WAI-ARIA 状态和属性。

Using the aria-labelledby attribute`aria-labelledby`属性用来表明某些元素的 id 是某一对象的标签。它被用来确定控件或控件组与它们标签之间的联系。使用诸如屏幕阅读器等辅助技术的用户通常使用 tabbing 在页面的不同区域间进行导航。如果一个输入元素、控件或控件组没有被分配一个 label 标签，那么屏幕阅读器就无法对其进行阅读。

使用 aria-hidden 属性本文用来说明如何使用 aria-hidden 属性。aria-hidden 属性可以用来控制一系列可访问 API 中的非交互内容的显示或隐藏。

使用 aria-label 属性aria-label 属性用来给当前元素加上的标签描述，接受字符串作为参数。是用不可视的方式给元素加 label（如果被描述元素存在真实的描述元素，可使用 aria-labelledby 属性作为来绑定描述元素和被描述元素来代替）。

参见
--

* 使用 ARIA：角色、状态和属性
使用 ARIA：角色、状态和属性
================

ARIA 定义了可以应用于元素的语义，这些语义分为 **roles**（定义一种用户界面元素）、**states** 和 **properties**，这些都是角色所支持的。作者必须在元素的生命周期中为其分配一个 ARIA 角色和适当的状态和属性，除非该元素已经具有适当的 ARIA 语义（通过使用适当的 HTML 元素）。添加 ARIA 语义只会向浏览器的无障碍 API 公开额外信息，而不会影响页面的 DOM。

角色
--

### 组件角色

* button
* checkbox (en-US)
* gridcell (en-US)
* link (en-US)
* menuitem
* menuitemcheckbox
* menuitemradio
* option
* progressbar (en-US)
* radio (en-US)
* scrollbar
* searchbox
* separator (when focusable)
* slider (en-US)
* spinbutton
* switch (en-US)
* tab (en-US)
* tabpanel (en-US)
* textbox (en-US)
* treeitem
### 复合角色

下面的技术描述了每个复合角色及其必需和可选的子角色。

* combobox
* grid (en-US) (包含 row (en-US), gridcell (en-US), rowheader, columnheader)
* listbox (包含 option)
* menu
* menubar
* radiogroup (en-US) (参考 radio)
* tablist (包含 tab (en-US) 和 tabpanel (en-US))
* tree
* treegrid
### 文档结构角色

* application (en-US)
* article (en-US)
* cell (en-US)
* columnheader
* definition
* directory
* document (en-US)
* feed
* figure (en-US)
* group (en-US)
* heading (en-US)
* img
* list
* listitem
* math
* none
* note
* presentation (en-US)
* row (en-US)
* rowgroup (en-US)
* rowheader
* separator
* table (en-US)
* term
* toolbar (en-US)
* tooltip
### 具有里程碑意义的角色

* banner (en-US)
* complementary (en-US)
* contentinfo (en-US)
* form (en-US)
* main (en-US)
* navigation (en-US)
* region (en-US)
* search (en-US)
### 实时区域角色

* alert (en-US)
* log (en-US)
* marquee
* status (en-US)
* timer (en-US)
### 窗口角色

* alertdialog (en-US)
* dialog (en-US)
状态和属性
-----

### 组件属性

* aria-autocomplete
* aria-checked
* aria-current
* aria-disabled
* aria-errormessage
* aria-expanded
* aria-haspopup
* aria-hidden
* aria-invalid
* aria-label
* aria-level
* aria-modal
* aria-multiline
* aria-multiselectable
* aria-orientation
* aria-placeholder
* aria-pressed
* aria-readonly
* aria-required
* aria-selected
* aria-sort
* aria-valuemax
* aria-valuemin
* aria-valuenow
* aria-valuetext
### 实时区域属性

* aria-live
* aria-relevant
* aria-atomic
* aria-busy
### 拖放属性

* aria-dropeffect
* aria-dragged
### 关系属性

* aria-activedescendant (en-US)
* aria-colcount
* aria-colindex
* aria-colspan
* aria-controls
* aria-describedby
* aria-details (en-US)
* aria-errormessage
* aria-flowto
* aria-labelledby
* aria-owns
* aria-posinset
* aria-rowcount
* aria-rowindex
* aria-rowspan
* aria-setsize
### MicrosoftEdge 特定的属性

* x-ms-aria-flowfrom (en-US) 
非标准
使用 aria-hidden 属性
=================

本文用来说明如何使用 aria-hidden 属性。aria-hidden 属性可以用来控制一系列可访问 API 中的非交互内容的显示或隐藏。

描述
--

把 `aria-hidden="true"` 加到元素上会把该元素和它的所有子元素从无障碍树上移除。这样做可以通过隐藏下列内容来提升使用辅助技术的用户体验：

* 纯装饰性的内容，如图标、图片
* 重复的内容，如重复的文本
* 屏幕外或被折叠的内容，如菜单

根据无障碍的第四条规则，`aria-hidden="true"` 不应该被用在可聚焦的元素上。而且，由于这个属性是可以被子元素继承的，它也不应该被用在可聚焦元素的父元素上。

如果父元素带有 `aria-hidden="true"` ，那么即使使用 `aria-hidden="false"` 也无法将该元素显示出来。

**警告：** WAI-ARIA Authoring Practices 1.1 提示 `aria-hidden="false"` 在现阶段 各个浏览器中表现不同.

### 比较 `aria-hidden="true"`， `role="presentation"` 和 `role="none"`

表面上，`aria-hidden="true"`，`role="presentation"`，和`role="none"` 很相似，因为这三者都有以下特性：

* 根据辅助即使隐藏页面内容
* 无法在可聚焦元素上使用
* 无法在可互动元素的父级元素上使用

尽管有上面这些相同点，但是各个属性的意图是不同的。

* `aria-hidden="true"` 会把整个元素从无障碍 API 中移除
* `role="presentation"` 和`role="none"` 会将元素从语义上移除，仍然会将元素暴露给辅助技术。
### 可选值

`false`

（默认）元素会暴露给无障碍 API。

`true`

元素不会暴露给无障碍 API。

`undefined`

（默认）客户端决定元素是否暴露给无障碍 API。

示例
--


```html
<i class="icon" aria-hidden="true" />
```

无障碍问题
-----

最佳实践
----

`aria-hidden="true"` 在以下场景不应该被使用：

* HTML 的`hidden`属性被设置了
* 祖先元素被`display: none`属性设置成不显示状态
* 祖先元素被`visibility: hidden`属性设置成不显示状态

在以上三个场景中，元素已经被隐藏，从可访问树种移除了，无需再添加`aria-hidden="true"`属性。

规范
--

| Specification |
| --- |
| Accessible Rich Internet Applications (WAI-ARIA) # aria-hidden |

另见
--

* 使用展示角色 (en-US)
* role="none"
使用 aria-label 属性
================

aria-label 属性用来给当前元素加上的标签描述，接受字符串作为参数。是用不可视的方式给元素加 label（如果被描述元素存在真实的描述元素，可使用 aria-labelledby 属性作为来绑定描述元素和被描述元素来代替）。

aria-label 属性可以用在任何典型的 HTML 元素中，并不需要配合特定的 ARIA role 才能使用。

### Value

string

### 对于用户代理和辅助技术的可能影响

**备注：** 由于辅助技术处理这一技术的差异导致选项信息可能不同。以上所提供的信息只是其中可能的一种，而非一般情况。

示例
--

#### 示例 1：多标签（Multiple Labels）

在下面的示例中，按钮（button）元素被定义为一个关闭（close）按钮，按钮中间有一个“X”字符。辅助软件并不能知道 X 是什么意思，所以需要 aria-label 标签来为辅助设备提供相应的标识来告诉它这个 button 是 close 的作用。


```html
<button aria-label="Close" onclick="myDialog.close()">X</button>
```

### 说明

最常见的对于标签的无障碍 API 就是可访问的 name 属性。

### ARIA roles 的使用

基本标记中的全部元素。

### ARIA 相关技术

* Using the aria-labelledby attribute
### 兼容性

有待讨论：为通常的 UA 和 AT 产品组合提供支持信息。

### 额外资源

* WAI-ARIA specification for aria-label
ARIA：listitem 角色
================

ARIA `listitem` 角色可用于标识项目列表中的项目。它通常与 `list` 角色（用于标识列表容器）结合使用。


```html
<section role="list">
  <div role="listitem">列表项 1</div>
  <div role="listitem">列表项 2</div>
  <div role="listitem">列表项 3</div>
</section>
```

描述
--

任何由外部容器和内部元素列表组成的内容都可以分别使用 `list` 和 `listitem` 容器识别为辅助技术。

关于应该使用哪些元素来标记列表和列表项没有硬性规定，但是你应该确保列表项在列表的上下文中有意义，例如购物清单、食谱步骤、行车路线。

**备注：** 如果可能，你应该使用适当的语义化 HTML 元素来标记列表及列表项，如 `<ul>`、`<ol>` 和 `<li>`。有关完整示例，请参阅最佳实践。

### 关联的 WAI-ARIA 角色、状态和属性

list

项目列表。角色为 `list` 的元素必须有一个或多个角色为 `listitem` 的元素作为子元素，一个或多个角色为 `group` 的元素具有一个或多个具有 `listitem` 角色的元素作为子元素。

group (en-US)

相关对象的集合，在嵌套在列表中时仅限于列表项，其重要性不足以在页面目录中拥有自己的位置。

最佳实践
----

仅在必要时使用 `role="list"` 和 `role="listitem"`。例如，无法控制 HTML 但能够在之后动态使用 JavaScript 提升无障碍的时候。

与 HTML `<ol>` 和 `<ul>` 不同，ARIA `list` 角色不区分有序列表和无序列表。如果可能，你应该使用适当的语义 HTML 元素来标记列表（`<ol>` 和 `<ul>`）和列表项（`<li>`）。例如，我们上面的例子应该改写如下：


```html
<ul>
  <li>列表项 1</li>
  <li>列表项 2</li>
  <li>列表项 3</li>
</ul>
```


或者如果列表项的顺序很重要，则使用有序列表：


```html
<ol>
  <li>列表项 1</li>
  <li>列表项 2</li>
  <li>列表项 3</li>
</ol>
```


**备注：** ARIA `list` / `listitem` 角色不区分有序列表和无序列表。

**备注：** 给列表添加 CSS 样式 `list-style: none;` 移除列表语义。添加 `role="listitem"` 获得列表语义。

**备注：** 如果要标记将用作选项卡式界面的项目列表，则应改为使用 `tab`、`tabpanel` 和 `tablist` 角色。

规范
--

| Specification |
| --- |
| Accessible Rich Internet Applications (WAI-ARIA) # listitem |

参见
--

* HTML `<li>` 元素
* HTML `<ul>` 元素
* HTML `<ol>` 元素
* ARIA：`list` 角色
* ARIA：`group` 角色 (en-US)
* 无障碍对象模型
* HTML 中的 ARIA
* ARIA 列表示例 — by Scott O'Hara
ARIA：list 角色
============

ARIA `list` 角色可用于标识项目列表。它通常与 `listitem` 角色结合使用，该角色用于标识包含在列表中的列表项。


```html
<section role="list">
  <div role="listitem">列表项 1</div>
  <div role="listitem">列表项 2</div>
  <div role="listitem">列表项 3</div>
</section>
```

描述
--

任何由外部容器和内部元素列表组成的内容都可以分别使用 `list` 和 `listitem` 容器识别为辅助技术。一个 `list` 必须有一个或多个 `listitem` 子级，或者，有一个或多个 `group` 作为子级，每个 `group`有一个或多个 `listitem` 作为子项。

关于应该使用哪些元素来标记 `list` 和 `listitem` 没有硬性规定，但是你应该确保 `listitem` 在列表的上下文中有意义，例如购物清单、食谱步骤、行车路线。

**警告：** 如果可能，你应该使用适当的语义化 HTML 元素来标记 `list` 及其 `listitem`，如 `<ul>`、`<ol>` 和 `<li>`。有关完整示例，请参阅 最佳实践。

### 关联的 WAI-ARIA 角色、状态和属性

listitem

列表或目录中的单个项目。角色为 listitem 的元素只能在角色为 `list` 或 `group` 的元素中找到。

group (en-US)

相关对象的集合，在嵌套在列表中时仅限于列表项，其重要性不足以在页面目录中拥有自己的位置。

最佳实践
----

仅在必要时使用 `role="list"` 和 `role="listitem"`。例如，无法控制 HTML 但能够在之后动态使用 JavaScript 提升无障碍的时候。

与 HTML `<ol>` 和 `<ul>` 不同，ARIA `list` 角色不区分有序列表和无序列表。如果可能，你应该使用适当的语义 HTML 元素来标记列表（`<ol>` 和 `<ul>`）和列表项（`<li>`）。例如，我们上面的例子应该改写如下：


```html
<ul>
  <li>列表项 1</li>
  <li>列表项 2</li>
  <li>列表项 3</li>
</ul>
```


或者如果列表项的顺序很重要，则使用有序列表：


```html
<ol>
  <li>列表项 1</li>
  <li>列表项 2</li>
  <li>列表项 3</li>
</ol>
```


**备注：** ARIA `list` / `listitem` 角色不区分有序列表和无序列表。

顺便说一句，请注意，如果你使用 `<ol>` 或 `<ul>` 的语义 HTML 元素并应用 `presentation` (en-US) 角色，则每个子 `li` 元素都会继承 `presentation` 角色，因为 ARIA 需要 `listitem` 元素具有父 `list` 元素。因此，`li` 元素不会暴露给辅助技术，但是包含在这些 `li` 元素中的元素，包括嵌套列表，对辅助技术是可见的。

**备注：** 如果要标记将用作选项卡式界面的项目列表，则应改为使用 `tab`、`tabpanel` 和 `tablist` 角色。

规范
--

| Specification |
| --- |
| Accessible Rich Internet Applications (WAI-ARIA) # list |

参见
--

* `<ul>` 元素
* `<ol>` 元素
* `<li>` 元素
* ARIA：listitem 角色
* ARIA：group 角色 (en-US)
* ARIA 列表示例——由 Scott O'Hara 撰写
* Accessibility Object Model
* ARIA in HTML
JavaScript 指南
=============

JavaScript 指南向你介绍如何使用 JavaScript，并且给出了语言概述。如果你需要了解某些语言特性的详细信息，请参阅 JavaScript 参考。

介绍
--

概述：介绍

* 关于这份指南
* 关于 JavaScript
* JavaScript 与 Java
* ECMAScript
* 工具
* Hello World
语法与数据类型
-------

概述：语法与数据类型

* 基本语法与注释
* 声明
* 变量作用域
* 变量提升
* 数据结构和类型
* 字面量
控制流与错误处理
--------

概述：控制流与错误处理

* `if...else`
* `switch`
* `try`/`catch`/`throw`
* Error 对象
循环与迭代
-----

概述：循环与迭代

* `for`
* `while`
* `do...while`
* `break`/`continue`
* `for..in`
* `for..of`
函数
--

概述：函数

* 定义函数
* 调用函数
* 函数作用域
* 闭包
* arguments 对象 和 参数
* 箭头函数
表达式和运算符
-------

概述：表达式和运算符

* 赋值
* 比较
* 算术运算符
* 位运算
* 逻辑运算符
* 条件（三元）运算符
数字与日期
-----

概述：数字与日期

* `Number` 字面量
* `Number` 对象
* `Math` 对象
* `Date` 对象
文本格式化
-----

概述：文本格式化

* 字符串字面量
* 字符串对象
* 模版字面量
* 国际化
* 正则表达式
索引集合
----

概述：索引集合

* 数组
* 类型数组
带键集合
----

概述：带键集合

* `Map`
* `WeakMap`
* `Set`
* `WeakSet`
处理对象
----

概述：处理对象

* 对象和属性
* 创建对象
* 定义方法
* getter 和 setter
对象模型的细节
-------

概述：对象模型的细节

* 基于原型的面向对象编程
* 创建对象层次结构
* 继承
Promises
--------

概述：Promises

* 约定
* 链式调用
* 错误传递
* 组合
* 时序
迭代器与生成器
-------

概述：迭代器与生成器

* 迭代器
* 可迭代对象
* 生成器
元编程
---

概述：元编程

* `Proxy`
* Handlers 和 traps
* 撤销 Proxy
* `Reflect`
JavaScript 模块
-------------

概述：JavaScript 模块

* 导出模块
* 导入模块
* 默认导出
* 重命名模块
* 合并模块
* 动态加载模块
* 下一页 »
并发模型与事件循环
=========

JavaScript 有一个基于**事件循环**的并发模型，事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。这个模型与其他语言中的模型截然不同，比如 C 和 Java。

运行时概念
-----

接下来的内容解释了这个理论模型。现代 JavaScript 引擎实现并着重优化了以下描述的这些语义。

### 可视化描述

![Stack, heap, queue](/zh-CN/docs/Web/JavaScript/Event_loop/the_javascript_runtime_environment_example.svg)

### 栈

函数调用形成了一个由若干帧组成的栈。


```js
function foo(b) {
  let a = 10;
  return a + b + 11;
}

function bar(x) {
  let y = 3;
  return foo(x \* y);
}

console.log(bar(7)); // 返回 42
```


当调用 `bar` 时，第一个帧被创建并压入栈中，帧中包含了 `bar` 的参数和局部变量。当 `bar` 调用 `foo` 时，第二个帧被创建并被压入栈中，放在第一个帧之上，帧中包含 `foo` 的参数和局部变量。当 `foo` 执行完毕然后返回时，第二个帧就被弹出栈（剩下 `bar` 函数的调用帧）。当 `bar` 也执行完毕然后返回时，第一个帧也被弹出，栈就被清空了。

### 堆

对象被分配在堆中，堆是一个用来表示一大块（通常是非结构化的）内存区域的计算机术语。

### 队列

一个 JavaScript 运行时包含了一个待处理消息的消息队列。每一个消息都关联着一个用以处理这个消息的回调函数。

在 事件循环 期间的某个时刻，运行时会从最先进入队列的消息开始处理队列中的消息。被处理的消息会被移出队列，并作为输入参数来调用与之关联的函数。正如前面所提到的，调用一个函数总是会为其创造一个新的栈帧。

函数的处理会一直进行到执行栈再次为空为止；然后事件循环将会处理队列中的下一个消息（如果还有的话）。

事件循环
----

之所以称之为 **事件循环**，是因为它经常按照类似如下的方式来被实现：


```js
while (queue.waitForMessage()) {
  queue.processNextMessage();
}
```


`queue.waitForMessage()` 会同步地等待消息到达 (如果当前没有任何消息等待被处理)。

### "执行至完成"

每一个消息完整地执行后，其他消息才会被执行。这为程序的分析提供了一些优秀的特性，包括：当一个函数执行时，它不会被抢占，只有在它运行完毕之后才会去运行任何其他的代码，才能修改这个函数操作的数据。这与 C 语言不同，例如，如果函数在线程中运行，它可能在任何位置被终止，然后在另一个线程中运行其他代码。

这个模型的一个缺点在于当一个消息需要太长时间才能处理完毕时，Web 应用程序就无法处理与用户的交互，例如点击或滚动。为了缓解这个问题，浏览器一般会弹出一个“这个脚本运行时间过长”的对话框。一个良好的习惯是缩短单个消息处理时间，并在可能的情况下将一个消息裁剪成多个消息。

### 添加消息

在浏览器里，每当一个事件发生并且有一个事件监听器绑定在该事件上时，一个消息就会被添加进消息队列。如果没有事件监听器，这个事件将会丢失。所以当一个带有点击事件处理器的元素被点击时，就会像其他事件一样产生一个类似的消息。

函数 `setTimeout` 接受两个参数：待加入队列的消息和一个时间值（可选，默认为 0）。这个时间值代表了消息被实际加入到队列的最小延迟时间。如果队列中没有其他消息并且栈为空，在这段延迟时间过去之后，消息会被马上处理。但是，如果有其他消息，`setTimeout` 消息必须等待其他消息处理完。因此第二个参数仅仅表示最少延迟时间，而非确切的等待时间。

下面的例子演示了这个概念（`setTimeout` 并不会在计时器到期之后直接执行）：


```js
const s = new Date().getSeconds();

setTimeout(function () {
  // 输出 "2"，表示回调函数并没有在 500 毫秒之后立即执行
  console.log("Ran after " + (new Date().getSeconds() - s) + " seconds");
}, 500);

while (true) {
  if (new Date().getSeconds() - s >= 2) {
    console.log("Good, looped for 2 seconds");
    break;
  }
}
```

### 零延迟

零延迟并不意味着回调会立即执行。以 0 为第二参数调用 `setTimeout` 并不表示在 0 毫秒后就立即调用回调函数。

其等待的时间取决于队列里待处理的消息数量。在下面的例子中，`"这是一条消息"` 将会在回调获得处理之前输出到控制台，这是因为延迟参数是运行时处理请求所需的最小等待时间，但并不保证是准确的等待时间。

基本上，`setTimeout` 需要等待当前队列中所有的消息都处理完毕之后才能执行，即使已经超出了由第二参数所指定的时间。


```js
(function () {
  console.log("这是开始");

  setTimeout(function cb() {
    console.log("这是来自第一个回调的消息");
  });

  console.log("这是一条消息");

  setTimeout(function cb1() {
    console.log("这是来自第二个回调的消息");
  }, 0);

  console.log("这是结束");
})();

// "这是开始"
// "这是一条消息"
// "这是结束"
// "这是来自第一个回调的消息"
// "这是来自第二个回调的消息"
```

### 多个运行时互相通信

一个 web worker 或者一个跨域的 `iframe` 都有自己的栈、堆和消息队列。两个不同的运行时只能通过 `postMessage` 方法进行通信。如果另一个运行时侦听 `message` 事件，则此方法会向该运行时添加消息。

永不阻塞
----

JavaScript 的事件循环模型与许多其他语言不同的一个非常有趣的特性是，它永不阻塞。处理 I/O 通常通过事件和回调来执行，所以当一个应用正等待一个 IndexedDB 查询返回或者一个 XHR 请求返回时，它仍然可以处理其他事情，比如用户输入。

由于历史原因有一些例外，如 `alert` 或者同步 XHR，但应该尽量避免使用它们。注意，例外的例外也是存在的（但通常是实现错误而非其他原因）。