DOM

现行标准 — 最后更新

参与:
GitHub whatwg/dom (新问题, 开放的问题)
在 Matrix 上聊天
提交:
GitHub whatwg/dom/commits
此提交的快照
@thedomstandard
测试:
web-platform-tests dom/ (进行中的工作)
翻译 (非规范性)
日本語
简体中文

摘要

DOM 定义了一个平台中立的模型,用于事件、活动中止和节点树。

1. 基础设施

本规范依赖于现行标准的基础设施标准。[INFRA]

本规范中使用的一些术语定义在编码选择器Web IDLXMLXML中的命名空间中。[ENCODING][SELECTORS4][WEBIDL][XML][XML-NAMES]

当需要扩展时,可以相应地更新 DOM 标准,或者可以编写一个新标准,该标准可以利用为 适用的规范 提供的可扩展性钩子。

1.1.

是一个有限的层次树结构。树的顺序是对的先序、深度优先遍历。

参与的对象有一个父节点,它要么是 null,要么是一个对象,并且有子节点,它是一个对象的有序集合。对象A父节点是对象B,则AB子节点

对象的是它自己,如果它的为null,否则它的根是它的的根。的根是参与该的任意对象,而该对象的为null。

如果对象A是对象B,或者对象A是对象C,而CB后代,则对象A被称为对象B后代

包含后代是指一个对象或其后代之一。

当且仅当BA后代时,称对象A为对象B祖先

包含祖先是指一个对象或其祖先之一。

当且仅当BA共享相同的非空父节点时,称对象A为对象B同胞

包含同胞是指一个对象或其同胞之一。

如果AB在同一个中,并且A树的顺序中位于B之前,则称对象A先于对象B

如果AB在同一个中,并且A树的顺序中位于B之后,则称对象A继于对象B

一个对象的第一个子节点是其第一个子节点,如果它没有子节点,则为 null。

一个对象的最后一个子节点是其最后一个子节点,如果它没有子节点,则为 null。

一个对象的前一个同胞是指其第一个先于同胞,如果没有,则为 null。

一个对象的下一个同胞是指其第一个继于同胞,如果没有,则为 null。

一个对象的索引是其先于同胞的数量,如果没有,则为 0。

1.2. 有序集合

有序集合解析器接受一个字符串input,然后执行以下步骤:

  1. inputTokens在 ASCII 空白字符处分割input的结果。

  2. tokens为一个新的有序集合

  3. 对于inputTokens中的每个tokentoken附加到tokens

  4. 返回tokens

有序集合序列化器接受一个set,并返回使用U+0020 SPACE连接的set串联结果

1.3. 选择器

范围匹配选择器字符串selectors与一个node,请执行以下步骤:

  1. s解析选择器selectors的结果。[SELECTORS4]

  2. 如果s失败,则抛出一个"SyntaxError"DOMException

  3. 返回将选择器与树匹配的结果,其中snode使用范围根node[SELECTORS4]

选择器中的命名空间不计划支持,也不会添加。

1.4. 命名空间

验证qualifiedName,如果qualifiedName不符合QName生成规则,则抛出一个"InvalidCharacterError"DOMException

验证并提取namespacequalifiedName,请执行以下步骤:

  1. 如果namespace是空字符串,则将其设置为null。

  2. 验证qualifiedName

  3. prefix设为null。

  4. localName设为qualifiedName

  5. 如果qualifiedName包含U+003A (:),则:

    1. splitResult设为运行严格分割后得到的结果,参数为qualifiedName和U+003A (:)。

    2. prefix设置为splitResult[0]。

    3. localName设置为splitResult[1]。

  6. 如果prefix非null且namespace为null,则抛出一个"NamespaceError"DOMException

  7. 如果prefix是"xml"且namespace不是XML命名空间,则抛出一个"NamespaceError"DOMException

  8. 如果qualifiedNameprefix是"xmlns"且namespace不是XMLNS命名空间,则抛出一个"NamespaceError"DOMException

  9. 如果namespaceXMLNS命名空间,且qualifiedNameprefix都不是"xmlns",则抛出一个"NamespaceError"DOMException

  10. 返回namespaceprefixlocalName

2. 事件

2.1. “DOM 事件”简介

在整个 Web 平台中,事件派发到对象,以标识发生的事件,例如网络活动或用户交互。这些对象实现了EventTarget接口,因此可以通过调用addEventListener()来添加事件监听器以观察事件

obj.addEventListener("load", imgFetched)

function imgFetched(ev) {
  // great success}

事件监听器可以通过使用removeEventListener()方法删除,传递相同的参数。

或者,也可以通过将AbortSignal传递给addEventListener(),然后调用控制器上持有信号的abort()来删除事件监听器

事件也是对象,并实现了Event接口(或派生接口)。在上面的例子中,ev事件ev作为参数传递给事件监听器回调(通常是如上所示的JavaScript函数)。事件监听器通过事件type属性值(上例中的"load")来区分事件。事件target属性值返回事件派发到的对象(如上例中的obj)。

虽然事件通常由用户代理在用户交互或某些任务完成时派发,但应用程序可以通过使用通常称为合成事件的方式派发事件

// add an appropriate event listener
obj.addEventListener("cat", function(e) { process(e.detail) })

// create and dispatch the event
var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}})
obj.dispatchEvent(event)

除了用于传递信号外,事件有时也用于让应用程序控制操作中的后续步骤。例如,作为表单提交的一部分,type属性值为"submit"的事件派发。如果调用了该事件preventDefault()方法,则表单提交将被终止。希望通过应用程序事件(合成事件)派发该功能的应用程序,可以使用dispatchEvent()方法的返回值。

if(obj.dispatchEvent(event)) {
  // event was not canceled, time for some magic}

当一个事件派发到一个参与(例如,一个元素)的对象时,它也可以到达该对象的祖先上的事件监听器。实际上,该对象的所有包含祖先捕获为true的事件监听器都将按照树的顺序被调用。然后,如果事件bubbles为true,则该对象的所有包含祖先捕获为false的事件监听器将按照相反的树的顺序被调用。

让我们看一个事件中如何工作的例子:

<!doctype html>
<html>
 <head>
  <title>Boring example</title>
 </head>
 <body>
  <p>Hello <span id=x>world</span>!</p>
  <script>
   function test(e) {
     debug(e.target, e.currentTarget, e.eventPhase)
   }
   document.addEventListener("hey", test, {capture: true})
   document.body.addEventListener("hey", test)
   var ev = new Event("hey", {bubbles:true})
   document.getElementById("x").dispatchEvent(ev)
  </script>
 </body>
</html>

debug函数将被调用两次。每次事件target属性值将是span元素。第一次currentTarget属性值将是document,第二次将是body元素eventPhase属性值将从CAPTURING_PHASE切换到BUBBLING_PHASE。如果为span元素注册了一个事件监听器eventPhase属性值将是AT_TARGET

2.2. 接口 Event

[Exposed=*]
interface Event {
  constructor(DOMString type, optional EventInit eventInitDict = {});

  readonly attribute DOMString type;
  readonly attribute EventTarget? target;
  readonly attribute EventTarget? srcElement; // legacy
  readonly attribute EventTarget? currentTarget;
  sequence<EventTarget> composedPath();

  const unsigned short NONE = 0;
  const unsigned short CAPTURING_PHASE = 1;
  const unsigned short AT_TARGET = 2;
  const unsigned short BUBBLING_PHASE = 3;
  readonly attribute unsigned short eventPhase;

  undefined stopPropagation();
           attribute boolean cancelBubble; // legacy alias of .stopPropagation()
  undefined stopImmediatePropagation();

  readonly attribute boolean bubbles;
  readonly attribute boolean cancelable;
           attribute boolean returnValue;  // legacy
  undefined preventDefault();
  readonly attribute boolean defaultPrevented;
  readonly attribute boolean composed;

  [LegacyUnforgeable] readonly attribute boolean isTrusted;
  readonly attribute DOMHighResTimeStamp timeStamp;

  undefined initEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false); // legacy
};

dictionary EventInit {
  boolean bubbles = false;
  boolean cancelable = false;
  boolean composed = false;
};

一个Event对象通常被称为一个事件。它用于标识某些事情已经发生,例如,一个图像已经完成下载。

一个潜在事件目标是 null 或一个EventTarget对象。

一个事件有一个关联的目标(一个潜在事件目标)。除非另有说明,否则它为 null。

一个事件有一个关联的相关目标(一个潜在事件目标)。除非另有说明,否则它为 null。

其他规范使用相关目标来定义一个relatedTarget属性。[UIEVENTS]

一个事件有一个关联的触摸目标列表(一个列表,包含零个或多个潜在事件目标)。除非另有说明,否则它为空列表。

触摸目标列表专门用于定义TouchEvent接口和相关接口。[TOUCH-EVENTS]

一个事件有一个关联的路径。一个路径是一个列表,包含结构体。每个结构体由一个调用目标(一个EventTarget对象)、一个在 shadow 树中的调用目标(一个布尔值)、一个shadow 调整后的目标(一个潜在事件目标)、一个相关目标(一个潜在事件目标)、一个触摸目标列表(一个列表,包含潜在事件目标)、一个关闭树的根(一个布尔值)和一个关闭树中的插槽(一个布尔值)。一个路径最初为空列表。

event = new Event(type [, eventInitDict])
返回一个新的event,其type属性值设置为typeeventInitDict参数允许通过同名对象成员设置bubblescancelable属性。
event . type
返回event的类型,例如"click"、"hashchange"或"submit"。
event . target
返回event分派的对象(其目标)。
event . currentTarget
返回当前正在调用其事件侦听器回调函数的对象。
event . composedPath()
返回event调用目标对象(将在其上调用侦听器的对象),但不包括任何节点,这些节点在shadow 树中,其shadow root模式为"closed"且无法从eventcurrentTarget到达。
event . eventPhase
返回事件的阶段,它是以下之一:NONECAPTURING_PHASEAT_TARGETBUBBLING_PHASE
event . stopPropagation()
当在中分派时,调用此方法会阻止event到达当前对象以外的任何对象。
event . stopImmediatePropagation()
调用此方法会阻止event在当前侦听器运行结束后到达任何注册的事件侦听器,并且当在中分派时,也会阻止event到达任何其他对象。
event . bubbles
根据event的初始化方式返回 true 或 false。如果event通过其目标祖先按相反的树顺序传播,则为 true;否则为 false。
event . cancelable
根据event的初始化方式返回 true 或 false。其返回值并不总是有意义,但 true 可以表示在分派event的过程中,部分操作可以通过调用preventDefault()方法来取消。
event . preventDefault()
如果在cancelable属性值为 true 时调用,并且在执行带有passive设置为 false 的侦听器时,通知导致分派event的操作需要取消。
event . defaultPrevented
如果成功调用preventDefault()表示取消,则返回 true;否则返回 false。
event . composed
根据event的初始化情况返回 true 或 false。如果event调用了超过作为其目标ShadowRoot节点的监听器,则返回 true;否则返回 false。
event . isTrusted
如果event由用户代理分派,则返回 true,否则返回 false。
event . timeStamp
以毫秒为单位返回event的时间戳,相对于发生时间。

type属性必须返回初始化时的值。当创建一个事件时,必须将该属性初始化为空字符串。

target获取步骤是返回this目标

srcElement获取步骤是返回this目标

currentTarget属性必须返回初始化时的值。当创建一个事件时,必须将该属性初始化为 null。

composedPath()方法的步骤为:

  1. composedPath成为一个空的列表

  2. path成为this路径

  3. 如果path为空,则返回composedPath

  4. currentTarget成为thiscurrentTarget属性值。

  5. 追加currentTargetcomposedPath

  6. currentTargetIndex设为 0。

  7. currentTargetHiddenSubtreeLevel设为 0。

  8. index设为path大小 - 1。

  9. index大于或等于 0 时:

    1. 如果path[index]的关闭树的根为 true,则将currentTargetHiddenSubtreeLevel增加 1。

    2. 如果path[index]的调用目标currentTarget,则将currentTargetIndex设置为index,并中断

    3. 如果path[index]的关闭树中的插槽为 true,则将currentTargetHiddenSubtreeLevel减少 1。

    4. 减少index的值 1。

  10. currentHiddenLevelmaxHiddenLevel设为currentTargetHiddenSubtreeLevel

  11. index设为currentTargetIndex - 1。

  12. index大于或等于 0 时:

    1. 如果path[index]的关闭树的根为 true,则将currentHiddenLevel增加 1。

    2. 如果currentHiddenLevel小于或等于maxHiddenLevel,则前置path[index]的调用目标composedPath

    3. 如果path[index]的关闭树中的插槽为 true,则:

      1. currentHiddenLevel减少 1。

      2. 如果currentHiddenLevel小于maxHiddenLevel,则将maxHiddenLevel设为currentHiddenLevel

    4. 减少index的值 1。

  13. currentHiddenLevelmaxHiddenLevel设为currentTargetHiddenSubtreeLevel

  14. index设为currentTargetIndex + 1。

  15. index小于path大小时:

    1. 如果path[index]的关闭树中的插槽为 true,则将currentHiddenLevel增加 1。

    2. 如果currentHiddenLevel小于或等于maxHiddenLevel,则追加path[index]的调用目标composedPath

    3. 如果path[index]的关闭树的根为 true,则:

      1. currentHiddenLevel减少 1。

      2. 如果currentHiddenLevel小于maxHiddenLevel,则将maxHiddenLevel设为currentHiddenLevel

    4. 增加index的值 1。

  16. 返回composedPath

eventPhase属性必须返回初始化时的值,该值必须是以下之一:

NONE(数值 0)
事件当前未被分派时处于此阶段。
CAPTURING_PHASE(数值 1)
当一个事件分派到一个参与的对象时,它将在到达其目标之前处于此阶段。
AT_TARGET(数值 2)
当一个事件分派时,它将在其目标上处于此阶段。
BUBBLING_PHASE(数值 3)
当一个事件分派到一个参与的对象时,它将在到达其目标后处于此阶段。

最初该属性必须初始化为NONE


每个事件都具有以下关联标志,最初都未设置:

stopPropagation()方法的步骤是设置this停止传播标志

cancelBubble获取步骤是如果this停止传播标志已设置,则返回 true;否则返回 false。

cancelBubble设置步骤是如果给定值为 true,则设置this停止传播标志;否则不执行任何操作。

stopImmediatePropagation()方法的步骤是设置this停止传播标志this立即停止传播标志

bubblescancelable属性必须返回初始化时的值。

设置取消标志,给定一个事件event,如果eventcancelable属性值为 true 并且event在被动侦听器中的标志未设置,则设置event取消标志,否则不执行任何操作。

returnValue获取步骤是如果this取消标志已设置,则返回 false;否则返回 true。

returnValue设置步骤是如果给定值为 false,则设置取消标志,并将this作为参数;否则不执行任何操作。

preventDefault()方法的步骤是将取消标志设置为this

在某些情况下,调用preventDefault()无效。建议用户代理在开发者控制台中记录具体原因,以帮助调试。

defaultPrevented获取步骤是如果this取消标志已设置,则返回 true;否则返回 false。

composed获取步骤是如果this合成标志已设置,则返回 true;否则返回 false。


isTrusted属性必须返回初始化时的值。当创建一个事件时,必须将该属性初始化为 false。

isTrusted是一个方便的属性,指示一个事件是否由用户代理分派(而不是使用dispatchEvent())。唯一的传统例外是click(),它导致用户代理分派一个isTrusted属性初始化为 false 的事件

timeStamp属性必须返回初始化时的值。


初始化一个event,使用typebubblescancelable,运行以下步骤:

  1. 设置event初始化标志

  2. 取消设置event停止传播标志立即停止传播标志取消标志

  3. 设置eventisTrusted属性为 false。

  4. 设置event目标为 null。

  5. eventtype属性设置为type

  6. eventbubbles属性设置为bubbles

  7. eventcancelable属性设置为cancelable

initEvent(type, bubbles, cancelable)方法的步骤为:

  1. 如果this分派标志已设置,则返回。

  2. 初始化this,使用typebubblescancelable

initEvent()事件构造函数是多余的,并且无法设置composed。它必须为了遗留内容而支持。

2.3. Window 接口的传统扩展

partial interface Window {
  [Replaceable] readonly attribute (Event or undefined) event; // legacy
};

每个 Window 对象都有一个关联的 当前事件(未定义或一个 Event 对象)。除非另有说明,否则它是未定义的。

event 的 getter 步骤是返回 this当前事件

强烈建议 Web 开发者依赖传递给事件监听器的 Event 对象,因为这将产生更具可移植性的代码。此属性在 workers 或 worklets 中不可用,并且对于在 shadow trees 中分派的事件是不准确的。

2.4. 接口 CustomEvent

[Exposed=*]
interface CustomEvent : Event {
  constructor(DOMString type, optional CustomEventInit eventInitDict = {});

  readonly attribute any detail;

  undefined initCustomEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional any detail = null); // legacy
};

dictionary CustomEventInit : EventInit {
  any detail = null;
};

事件 使用 CustomEvent 接口可以用于携带自定义数据。

event = new CustomEvent(type [, eventInitDict])
其工作方式类似于 Event 的构造函数,但 eventInitDict 参数现在还允许设置 detail 属性。
event . detail
返回创建 event 时的任何自定义数据。 通常用于合成事件。

detail 属性必须返回它初始化时的值。

initCustomEvent(type, bubbles, cancelable, detail) 方法的步骤如下:

  1. 如果 thisdispatch flag 已设置,则返回。

  2. 初始化 this ,包括 typebubblescancelable

  3. thisdetail 属性设置为 detail

2.5. 构造事件

规范可能会为所有或某些事件定义事件构造步骤。该算法接收一个事件event和一个EventIniteventInitDict,如内部事件创建步骤中所示。

这个构造方式可用于Event子类,它们具有比简单的初始化字典成员和IDL属性之间一对一映射更复杂的结构。

构造函数Event接口,或继承自Event接口的接口被调用时,必须运行以下步骤,给定参数typeeventInitDict

  1. 运行内部事件创建步骤,以获得event,使用此接口、null、当前时间和eventInitDict

  2. eventtype属性初始化为type

  3. 返回event

要使用eventInterface 创建事件,该接口必须是Event或继承自它的接口,并且可选地提供realm realm,运行以下步骤:

  1. 如果未提供realm,则将其设置为null。

  2. dictionary设置为将JavaScript值undefined转换为eventInterface构造函数所接受的字典类型的结果。(此字典类型将是EventInit或继承自它的字典类型。)

    如果需要成员,这种方法不起作用;请参见whatwg/dom#600

  3. 运行内部事件创建步骤,以eventInterfacerealm、该事件信号发生的时间和dictionary为参数,得到event

    在macOS中,输入操作的发生时间可以通过NSEvent对象的timestamp属性获得。

  4. eventisTrusted属性初始化为true。

  5. 返回event

创建事件用于需要分别创建分发事件的其他规范,而不是简单地触发事件。它确保事件的属性初始化为正确的默认值。

内部事件创建步骤,给定eventInterfacerealmtimedictionary,如下所示:

  1. 使用eventInterface创建一个新对象作为event的结果。如果realm非空,则使用该realm;否则,使用Web IDL中定义的默认行为。

    截至本文撰写时,Web IDL 尚未定义任何默认行为;请参见whatwg/webidl#135

  2. 设置event初始化标志

  3. eventtimeStamp属性初始化为给定timeevent相关全局对象相对高分辨率粗略时间

  4. 遍历dictionary中的membervalue,如果event有一个属性,其标识符member,则将该属性初始化为value

  5. 运行事件构造步骤,参数为eventdictionary

  6. 返回event

2.6. 定义事件接口

通常,在定义一个继承自Event的新接口时,请务必征求WHATWGW3C WebApps WG社区的反馈。

CustomEvent接口可以作为起点。然而,不要引入任何init*Event()方法,因为它们与构造函数是冗余的。继承自Event接口的接口中如果包含此类方法,也只是出于历史原因。

2.7. 接口 EventTarget

[Exposed=*]
interface EventTarget {
  constructor();

  undefined addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options = {});
  undefined removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options = {});
  boolean dispatchEvent(Event event);
};

callback interface EventListener {
  undefined handleEvent(Event event);
};

dictionary EventListenerOptions {
  boolean capture = false;
};

dictionary AddEventListenerOptions : EventListenerOptions {
  boolean passive;
  boolean once = false;
  AbortSignal signal;
};

一个 EventTarget 对象表示一个目标,当某些事情发生时,一个事件可以被派发到该目标。

每个 EventTarget 对象都有一个相关的事件监听器列表(一个由零个或多个事件监听器组成的列表)。它最初是空的列表。

一个事件监听器 可以用于观察特定的事件,它由以下部分组成:

虽然回调是一个 EventListener 对象,事件监听器 是一个更广泛的概念,如上所述。

每个 EventTarget 对象还有一个相关的获取父级算法, 该算法接收一个事件 event,并返回一个EventTarget 对象。除非另有说明,它返回null。

节点影子根节点文档会重写 获取父级算法。

每个 EventTarget 对象可以有一个相关的激活行为算法。该激活行为算法接收一个事件,如 派发 算法中所示。

这是因为用户代理在某些EventTarget 对象上执行某些操作,例如 area 元素,以响应其MouseEventtype 属性为click的合成事件。由于Web兼容性问题,它未能被移除,并且现在成为定义激活某些内容的固定方式。[HTML]

每个 EventTarget 对象如果具有激活行为,还可以同时(而非单独)具有遗留预激活行为算法 和遗留取消激活行为 算法。

这些算法仅存在于复选框和单选框的 input 元素中, 不适用于其他任何内容。[HTML]

target = new EventTarget();

创建一个新的EventTarget 对象,开发者可以使用它来派发并 监听事件

target . addEventListener(type, callback [, options])

type属性值为type事件附加一个事件侦听器callback参数设置将在事件分派时调用的回调函数

options为true时,监听器在捕获阶段触发;当为false或未设置时,监听器在冒泡阶段触发。无论设置如何,若事件处于目标阶段,监听器均会被触发。

options设置为true时,表示监听器为被动模式,不会调用preventDefault()来取消事件。

options设置为true时,表示监听器仅触发一次,触发后将被移除。

若为options指定了AbortSignal,当信号被中止时,监听器将被移除。

若已存在相同typecallbackcapture的事件监听器,则不会再次添加。

target . removeEventListener(type, callback [, options])

移除target中与typecallbackoptions匹配的事件监听器。

target . dispatchEvent(event)

派发event事件,并返回true,若事件的cancelable属性为false或未调用preventDefault(),否则返回false。

展开 options,请执行以下步骤:

  1. 如果options是布尔值,则返回options

  2. 返回options["capture"]。

进一步展开 options,请执行以下步骤:

  1. captureoptions展开的结果。

  2. once为false。

  3. passivesignal为null。

  4. 如果options是一个字典,则:

    1. once设置为options["once"]。

    2. 如果options["passive"] 存在,则将passive设置为options["passive"]。

    3. 如果options["signal"] 存在,则将signal设置为options["signal"]。

  5. 返回capturepassiveoncesignal

new EventTarget()构造函数步骤不执行任何操作。

由于其他地方声明的默认值,返回的EventTarget获取父级算法将返回null,并且它没有激活行为遗留预激活行为, 或遗留取消激活行为

将来我们可能会允许自定义获取父级算法。请告诉我们 这对您的程序是否有用。目前,所有作者创建的EventTarget 不参与树结构。

默认被动值,给定一个事件类型type和一个EventTarget eventTarget,由下列步骤决定:

  1. 若下列条件全部满足,则返回true:

  2. 返回false。

添加事件监听器,给定一个EventTarget 对象eventTarget和一个事件监听器listener,请执行以下步骤:

  1. eventTarget是一个ServiceWorkerGlobalScope 对象,其service worker脚本资源曾经评估过的标志被设置,且listener类型与任何service worker 事件类型属性值匹配,则向控制台报告一个警告,提示这可能不会产生预期结果。[SERVICE-WORKERS]

  2. listener信号不为null且已中止,则返回。

  3. listener回调为null,则返回。

  4. listener被动为null,则将其设置为listener默认被动值,根据listener类型eventTarget

  5. eventTarget事件监听器列表包含一个事件监听器,其类型listener类型回调listener回调,且捕获listener捕获,则追加 listenereventTarget事件监听器列表中。

  6. listener信号不为null,则添加以下中止步骤:

    1. 移除事件监听器,使用eventTargetlistener

添加事件监听器的概念是为了确保事件处理器使用相同的代码路径。[HTML]

addEventListener(type, callback, options) 方法步骤为:

  1. capturepassiveoncesignal进一步展开 options的结果。

  2. 添加事件监听器,使用this和一个事件监听器,其类型type回调callback捕获capture被动passive一次性once信号signal

移除事件监听器,给定一个EventTarget 对象eventTarget和一个事件监听器 listener,请执行以下步骤:

  1. 如果eventTargetServiceWorkerGlobalScope对象,并且它的服务工作者要处理的事件类型集合包含listener类型,那么报告一个警告到控制台,表明这可能不会产生预期的结果。[SERVICE-WORKERS]

  2. listenerremoved设置为true,并且eventTarget事件侦听器列表中移除listener

HTML 需要这个来定义事件处理器。[HTML]

移除所有事件监听器,给定一个EventTarget 对象eventTarget对其每个 listener事件监听器列表项,移除事件监听器,使用eventTargetlistener

HTML 需要这个来定义document.open()[HTML]

removeEventListener(type, callback, options) 方法步骤为:

  1. capture展开options的结果。

  2. 如果this事件 监听器列表 包含一个事件监听器, 其类型type回调callback,且捕获capture,则移除事件监听器,使用this和该事件监听器

事件侦听器列表不会包含具有相同typecallbackcapture的多个事件侦听器,因为添加事件侦听器会防止这种情况发生。

dispatchEvent(event)方法步骤为:

  1. event派发标志已设置,或其初始化标志未设置,则抛出一个“InvalidStateErrorDOMException

  2. eventisTrusted属性初始化为false。

  3. 返回派发 eventthis的结果。

2.8. 观察事件监听器

一般来说,开发者不会期望事件监听器的存在是可观察的。 事件监听器的影响由其回调决定。也就是说, 开发者添加一个无操作的事件监听器时不会期望它有任何副作用。

不幸的是,一些事件API的设计使得要高效实现它们就需要观察事件侦听器。这使得侦听器的存在是可观察的,即使是空的侦听器也可能对应用程序的行为产生显著的性能影响。例如,可以用于阻止异步滚动的触摸和滚轮事件。在某些情况下,可以通过仅在存在至少一个非被动侦听器时将事件指定为可取消来缓解这一问题。例如,非被动触摸事件侦听器必须阻止滚动,但如果所有侦听器都是被动的,则可以通过使触摸事件不可取消(从而忽略对preventDefault()的调用)来允许滚动并行开始。因此,分派事件的代码能够观察到非被动侦听器的缺失,并使用该信息来清除正在分派的事件的可取消属性。

理想情况下,任何新的事件API都应定义为不需要此属性。(请使用whatwg/dom进行讨论。)

获取遗留的服务工作者获取事件侦听器回调,给定一个ServiceWorkerGlobalScopeglobal,请运行以下步骤。这些步骤将返回一个EventListener对象的列表

  1. callbacks为« »。

  2. 对于每个 listenerglobal事件监听器列表

    1. 如果listener类型为"fetch",且 listener回调不为null,则追加 listener回调callbacks

  3. 返回callbacks

2.9. 分发事件

要将一个事件分发给一个目标,可选带有legacy target override flaglegacyOutputDidListenersThrowFlag,请按以下步骤操作:

  1. 设置event分发标志

  2. 如果未给出legacy target override flag,则将targetOverride设置为目标,否则设置为目标关联的文档[HTML]

    legacy target override flag仅由HTML使用,且仅当目标是一个窗口对象时使用。

  3. activationTarget设置为null。

  4. relatedTarget设置为针对目标重新定位eventrelatedTarget的结果。

  5. 如果目标不是relatedTarget目标eventrelatedTarget,则:

    1. touchTargets设置为一个新的列表

    2. 对于每个touchTarget,它在event触摸目标列表中,追加针对目标重新定位touchTarget的结果到touchTargets中。

    3. 通过event目标targetOverriderelatedTargettouchTargets,并设置为false,附加到事件路径

    4. 如果event是一个鼠标事件对象,且event类型属性为"click",则isActivationEvent为true;否则为false。

    5. 如果isActivationEvent为true且目标具有激活行为,则将activationTarget设置为目标

    6. 如果目标是一个slottable且已分配,则将slottable设置为目标,否则为null。

    7. slot-in-closed-tree设置为false。

    8. parent设置为调用目标获取父项结果的event

    9. parent非空时:

      1. 如果slottable非空:

        1. 断言:parent是一个插槽

        2. slottable设置为null。

        3. 如果parent是一个影子根,且它的模式是"closed",则将slot-in-closed-tree设置为true。

      2. 如果parent是一个slottable且已分配,则将slottable设置为parent

      3. relatedTarget设置为针对parent重新定位eventrelatedTarget的结果。

      4. touchTargets设置为一个新的列表

      5. 对于每个touchTarget ,它在event触摸目标列表中,追加针对parent重新定位touchTarget的结果到touchTargets中。

      6. 如果parent是一个窗口对象,或parent是一个节点目标parent包括影子在内的包容性祖先,则:

        1. 如果isActivationEvent为true,event冒泡属性为true,activationTarget为null,且parent具有激活行为,则将activationTarget设置为parent

        2. 附加到事件路径通过eventparent、null、relatedTargettouchTargets,并设置slot-in-closed-tree

      7. 否则,如果parentrelatedTarget,则将parent设置为null。

      8. 否则,将目标设置为parent,然后:

        1. 如果isActivationEvent为true,activationTarget为null,且目标具有激活行为,则将activationTarget设置为目标

        2. 附加到事件路径通过eventparent目标relatedTargettouchTargets,并设置slot-in-closed-tree

      9. 如果parent非空,则将parent设置为调用parent获取父项结果的event

      10. slot-in-closed-tree设置为false。

    10. clearTargetsStruct设置为event路径中的最后一个结构,其影子调整目标非空。

    11. 如果clearTargetsStruct影子调整目标clearTargetsStructrelatedTarget,或者clearTargetsStruct触摸目标列表中的事件目标对象是一个节点,且其是一个影子根,则clearTargets为true;否则为false。

    12. 如果activationTarget非空且activationTarget具有旧式预激活行为,则运行activationTarget旧式预激活行为

    13. 对于每个event路径中的struct,按逆序:

      1. 如果struct影子调整目标非空,则 将event事件阶段属性设置为AT_TARGET

      2. 否则,将event事件阶段属性设置为CAPTURING_PHASE

      3. 调用通过structevent、"捕获",以及如果给出的话legacyOutputDidListenersThrowFlag

    14. 对于每个event路径中的struct

      1. 如果struct影子调整目标非空,则 将event事件阶段属性设置为AT_TARGET

      2. 否则:

        1. 如果event冒泡属性为false,则继续

        2. event事件阶段属性设置为BUBBLING_PHASE

      3. 调用通过structevent、"冒泡",以及如果给出的话legacyOutputDidListenersThrowFlag

  6. event事件阶段属性设置为NONE

  7. event当前目标属性设置为null。

  8. event路径设置为空列表。

  9. 取消设置event分发标志停止传播标志,以及立即停止传播标志

  10. 如果clearTargets,则:

    1. event目标设置为null。

    2. eventrelatedTarget设置为null。

    3. event触摸目标列表设置为空列表。

  11. 如果activationTarget非空,则:

    1. 如果event取消标志未设置,则使用event运行activationTarget激活行为

    2. 否则,如果activationTarget具有旧式取消激活行为,则运行activationTarget旧式取消激活行为

  12. 如果event取消标志已设置,则返回false;否则返回true。

附加到事件路径,给定一个eventinvocationTargetshadowAdjustedTargetrelatedTargettouchTargets,以及slot-in-closed-tree,请运行这些步骤:

  1. invocationTargetInShadowTree设置为false。

  2. 如果invocationTarget是一个节点,且其是一个影子根,则将invocationTargetInShadowTree设置为true。

  3. root-of-closed-tree设置为false。

  4. 如果invocationTarget是一个影子根,且其模式是"closed",则将root-of-closed-tree设置为true。

  5. 追加一个新的结构event路径,其调用目标invocationTarget调用目标在影子树中invocationTargetInShadowTree影子调整目标shadowAdjustedTargetrelatedTargetrelatedTarget触摸目标列表touchTargets关闭树的根root-of-closed-tree,以及slot-in-closed-treeslot-in-closed-tree

调用,给定一个structevent阶段,以及可选的legacyOutputDidListenersThrowFlag,请运行这些步骤:

  1. event目标设置为event路径中的最后一个结构,其影子调整目标非空,且为structstruct之前的结构。

  2. eventrelatedTarget设置为structrelatedTarget

  3. event触摸目标列表设置为struct触摸目标列表

  4. 如果event停止传播标志已设置,则返回。

  5. 初始化event当前目标属性为struct调用目标

  6. listeners设置为event当前目标属性值的事件侦听器列表克隆

    这避免了在此点之后添加的事件侦听器被运行。请注意,由于已删除字段,移除仍然有影响。

  7. invocationTargetInShadowTree设置为struct调用目标在影子树中

  8. found设置为运行内部调用通过eventlisteners阶段invocationTargetInShadowTree,以及如果给出的话legacyOutputDidListenersThrowFlag的结果。

  9. 如果found为false且eventisTrusted属性为true, 则:

    1. originalEventType设置为event类型属性值。

    2. 如果event类型属性值匹配下表中的任意字符串,将event类型属性值设置为同一行匹配字符串旁的字符串,否则返回。

      事件类型 旧式事件类型
      "animationend" "webkitAnimationEnd"
      "animationiteration" "webkitAnimationIteration"
      "animationstart" "webkitAnimationStart"
      "transitionend" "webkitTransitionEnd"
    3. 内部调用通过eventlisteners阶段invocationTargetInShadowTree,以及如果给出的话legacyOutputDidListenersThrowFlag

    4. event类型属性值设置为originalEventType

内部调用,给定一个eventlisteners阶段invocationTargetInShadowTree,以及可选的legacyOutputDidListenersThrowFlag,请运行这些步骤:

  1. found 为 false。

  2. 对于每个 listenerlisteners 中,其 移除状态为 false:

    1. 如果 eventtype 属性值不是 listener类型,则 继续

    2. found 设为 true。

    3. 如果 phase 是 "capturing" 并且 listenercapture 为 false,则 继续

    4. 如果 phase 是 "bubbling" 并且 listenercapture 为 true,则 继续

    5. 如果 listeneronce 为 true,则 移除 listenereventcurrentTarget 属性值的 事件监听器列表

    6. global 成为 listener回调关联的领域全局对象

    7. currentEvent 为 undefined。

    8. 如果 global 是一个 Window 对象,则:

      1. currentEvent 设为 global当前事件

      2. 如果 invocationTargetInShadowTree 为 false,则将 global当前事件 设为 event

    9. 如果 listenerpassive 为 true,则设定 event被动监听器标志

    10. 如果 global 是一个 Window 对象,则 记录事件监听器的计时信息,使用 eventlistener

    11. 调用用户对象的操作,使用 listener回调,"handleEvent",«event»,以及 eventcurrentTarget 属性值。如果这会抛出一个异常 exception,则:

      1. 报告 exception,用于 listener回调的相应 JavaScript 对象的 关联领域全局对象

      2. 设置 legacyOutputDidListenersThrowFlag(如果提供)。

        legacyOutputDidListenersThrowFlag 仅被 Indexed Database API 使用。[INDEXEDDB]

    12. 取消设定 event被动监听器标志

    13. 如果 global 是一个 Window 对象,则将 global当前事件 设为 currentEvent

    14. 如果 event停止立即传播标志已设置,则返回 found

  3. 返回 found

2.10. 触发事件

要在target触发事件,事件名为e,可选地使用eventConstructor,并描述如何初始化IDL属性,以及legacy target override flag,请执行以下步骤:

  1. 如果未给出eventConstructor,则令eventConstructorEvent

  2. event为根据eventConstructor 创建事件的结果,且在target相关领域中。

  3. eventtype属性初始化为e

  4. 按照此算法调用时描述的内容初始化event的其他IDL属性。

    这也允许将isTrusted属性设置为false。

  5. 返回调度eventtarget的结果,并在设置时设置legacy target override flag

在 DOM 的上下文中,"Fire" 是创建、初始化和分派一个事件的缩写。Fire an event 使得这个过程更容易表达。

如果事件需要其 bubblescancelable 属性初始化, 可以这样写:“fire an event named submit at target with its cancelable attribute initialized to true”。

或者,当需要自定义构造函数时,可以这样写:“fire an event named click at target using MouseEvent with its detail attribute initialized to 1”。

有时返回值很重要:

  1. doAction 成为 firing an event named like at target 的结果。

  2. 如果 doAction 为真,那么……

2.11. 动作与事件的区别

一个事件表示一个发生的事情,而不是一个动作。换句话说,它代表一个算法的通知,并且可以用于影响该算法的未来执行过程(例如,通过调用preventDefault())。事件不得用于作为动作或启动某个算法的触发器。这不是它们的用途。

这里特别指出这一点是因为之前的DOM迭代中有一个与事件相关的“默认动作”的概念,这给人们带来了错误的理解。事件不代表或引发动作,它们只能用于影响正在进行的动作。

3. 中止正在进行的活动

虽然Promise没有内置的中止机制,但许多使用Promise的API需要中止语义。AbortController旨在通过提供abort()方法来支持这些需求,该方法可切换对应AbortSignal对象的状态。希望支持中止的API可以接受一个AbortSignal对象,并使用其状态来决定如何继续。

依赖于AbortController的API建议通过拒绝任何未决的Promise来响应abort(),并使用AbortSignalabort reason

一个假设的doAmazingness({ ... })方法可以通过接受AbortSignal对象来支持中止,类似如下:

const controller = new AbortController();
const signal = controller.signal;

startSpinner();

doAmazingness({ ..., signal })
  .then(result => ...)
  .catch(err => {
    if (err.name == 'AbortError') return;
    showUserErrorMessage();
  })
  .then(() => stopSpinner());

// …

controller.abort();

doAmazingness could be implemented as follows:

function doAmazingness({signal}) {
  return new Promise((resolve, reject) => {
    signal.throwIfAborted();

    // Begin doing amazingness, and call resolve(result) when done.
    // But also, watch for signals:
    signal.addEventListener('abort', () => {
      // Stop doing amazingness, and:
      reject(signal.reason);
    });
  });
}

不返回promise的API可以选择以类似的方式做出反应,或者选择完全不展示AbortSignal中止原因addEventListener()就是一个适合后者的API例子。

需要更精细控制的API可以根据需要扩展AbortControllerAbortSignal对象。

3.1. 接口 AbortController

[Exposed=*]
interface AbortController {
  constructor();

  [SameObject] readonly attribute AbortSignal signal;

  undefined abort(optional any reason);
};
controller = new AbortController()
返回一个新的controller,其signal被设置为新创建的AbortSignal对象。
controller . signal
返回与此对象关联的AbortSignal对象。
controller . abort(reason)
调用此方法将把reason存储在此对象的AbortSignal中止原因中,并向任何观察者发出信号,表示相关活动将被中止。如果reason未定义,则会存储一个"AbortError"DOMException

一个AbortController对象有一个关联的信号(一个AbortSignal对象)。

new AbortController()构造函数步骤如下:

  1. signal成为一个新的AbortSignal对象。

  2. 设置thissignalsignal

signal的getter步骤是返回thissignal

abort(reason)方法步骤是在signal abort上执行,带有reason如果给定。

AbortControllercontroller上带有可选的reason执行signal abort,如果reason被提供。

3.2. 接口AbortSignal

[Exposed=*]
interface AbortSignal : EventTarget {
  [NewObject] static AbortSignal abort(optional any reason);
  [Exposed=(Window,Worker), NewObject] static AbortSignal timeout([EnforceRange] unsigned long long milliseconds);
  [NewObject] static AbortSignal _any(sequence<AbortSignal> signals);

  readonly attribute boolean aborted;
  readonly attribute any reason;
  undefined throwIfAborted();

  attribute EventHandler onabort;
};
AbortSignal . abort(reason)
返回一个AbortSignal实例,其中止原因设置为reason(如果未定义则为"AbortError"DOMException)。
AbortSignal . any(signals)
返回一个AbortSignal实例,该实例将在任一signals中止时中止。其中止原因将被设置为导致中止的signals中的某一个。
AbortSignal . timeout(milliseconds)
返回一个AbortSignal实例,该实例将在milliseconds毫秒后中止。其中止原因将被设置为"TimeoutError"DOMException
signal . aborted
如果signalAbortController已发出中止信号,则返回true;否则返回false。
signal . reason
返回signal中止原因
signal . throwIfAborted()
如果signalAbortController已发出中止信号,则抛出signal中止原因;否则不执行任何操作。

一个AbortSignal对象有一个关联的中止原因(一个JavaScript值),其初始状态为未定义。

一个AbortSignal对象有一个关联的中止算法(一组将在中止时执行的算法),其初始状态为空。

中止算法使得具有复杂要求的API能够合理地响应abort()。例如,给定API的中止原因可能需要传播到跨线程环境,例如service worker。

一个AbortSignal对象有一个依赖项(一个布尔值),其初始状态为false。

一个AbortSignal对象有一个关联的源信号(一组AbortSignal对象),其初始状态为空。

一个AbortSignal对象有一个关联的依赖信号(一组依赖于对象的AbortSignal对象),其初始状态为空。


静态方法abort(reason)的步骤如下:

  1. signal成为一个新的AbortSignal对象。

  2. signal中止原因设置为reason,如果给定;否则设置为新的"AbortError"DOMException

  3. 返回signal

静态方法timeout(milliseconds)的步骤如下:

  1. signal成为一个新的AbortSignal对象。

  2. global成为signal相关全局对象

  3. 在超时后运行步骤,给定global、"AbortSignal-timeout"、milliseconds,以及以下步骤:

    1. 在全局任务队列中排队,在global上,基于signal和新的"TimeoutError"DOMException执行signal abort

    在此超时时间内,如果signal已为其abort事件注册了任何事件监听器,则必须从globalsignal保持一个强引用。

  4. 返回signal

静态方法any(signals)的步骤是返回创建一个依赖的中止信号的结果,使用signalsAbortSignal当前领域

abortedgetter步骤是返回true如果this中止;否则返回false。

reasongetter步骤是返回this中止原因

throwIfAborted()方法步骤是抛出this中止原因,如果this中止

此方法主要用于当接受AbortSignal的函数希望在特定检查点抛出(或返回一个被拒绝的promise),而不是将AbortSignal传递给其他方法时。例如,以下函数允许在每次尝试轮询条件之间中止。这为中止轮询过程提供了机会,即使实际的异步操作(即await func())不接受AbortSignal

async function waitForCondition(func, targetValue, { signal } = {}) {
  while (true) {
    signal?.throwIfAborted();

    const result = await func();
    if (result === targetValue) {
      return;
    }
  }
}

属性 onabort 是一个 事件处理程序 IDL 属性,用于 onabort 事件处理程序,其 事件处理程序事件类型abort

AbortSignal 对象的更改代表了相应的 AbortController 对象的意图,但观察 AbortSignal 对象的 API 可以选择忽略这些更改。例如,如果操作已经完成。


AbortSignal 对象的 中止原因 不为未定义时, 该对象被认为是 已中止

要向 AbortSignal 对象 signal添加 一个算法 algorithm

  1. 如果 signal中止,则返回。

  2. algorithm 追加到 signal中止算法中。

发出中止信号, 给定一个 AbortSignal 对象 signal 和一个可选的 reason

  1. 如果 signal 已经 中止,则返回。

  2. signal中止原因 设为 reason(如果提供);否则设为一个新的 "AbortError" DOMException

  3. dependentSignalsToAbort 设为一个新的 列表

  4. 对于每个 dependentSignalsignal依赖信号 中:

    1. 如果 dependentSignal 尚未 中止,则:

      1. dependentSignal中止原因 设为 signal中止原因

      2. 附加 dependentSignaldependentSignalsToAbort

  5. 运行中止步骤 对于 signal

  6. 对于每个 dependentSignaldependentSignalsToAbort 中,运行中止步骤 对于 dependentSignal

运行中止步骤 对于一个 AbortSignal signal

  1. 对于每个 algorithmsignal中止算法 中:运行 algorithm

  2. 清空 signal中止算法

  3. 触发事件,名为 abort,在 signal 上。

要从一组 AbortSignal 对象 signals创建一个依赖中止信号, 使用 signalInterface(必须是 AbortSignal 或继承自它的接口)和 realm

  1. resultSignal 成为一个 新的 使用 realm 实现 signalInterface 的对象。

  2. 对于 signals 中的每一个 signal:如果 signal中止, 则将 resultSignal中止原因 设置为 signal中止原因,然后返回 resultSignal

  3. resultSignal依赖性 设置为 true。

  4. 对于 signals 中的每一个 signal

    1. 如果 signal依赖性 为 false,则:

      1. signal 追加到 resultSignal源信号中。

      2. resultSignal 追加到 signal依赖信号中。

    2. 否则,对于 signal源信号 中的每一个 sourceSignal

      1. 断言:sourceSignal 不是 已中止的, 也不是 依赖的

      2. sourceSignal 追加到 resultSignal源信号中。

      3. resultSignal 追加到 sourceSignal依赖信号中。

  5. 返回 resultSignal

3.2.1. 垃圾回收

一个非 中止的 依赖的 AbortSignal 对象,在其 源信号 非空且其已注册事件监听器 监听其 abort 事件或其 中止算法 非空时,不能被垃圾回收。

3.3. 在 API 中使用 AbortControllerAbortSignal 对象

任何使用 promises 表示可以中止操作的 Web 平台 API 必须遵循以下规则:

返回 promise 的方法 doAmazingness(options) 的方法步骤可能如下:

  1. global成为相关全局对象

  2. p成为一个新的 promise

  3. 如果 options中存在["signal"]成员,则:

    1. signal成为options["signal"]。

    2. 如果 signal已中止, 则拒绝p,使用signal中止原因,并返回 p

    3. 添加以下中止步骤signal

      1. 停止做令人惊叹的事情。

      2. 拒绝p,使用signal中止原因

  4. 并行运行这些步骤:

    1. amazingResult成为做一些令人惊叹的事情的结果。

    2. 在全局任务队列中添加一个任务,任务源为global,以解决p,并将amazingResult作为参数。

  5. 返回 p

不使用 promises 的 API 仍应尽可能遵循上述规则。

4. 节点

4.1. “DOM”简介

在其原始意义上,“DOM”是一个用于访问和操作文档(特别是HTML和XML文档)的API。在本规范中,术语“文档”用于任何基于标记的资源,从简短的静态文档到包含丰富多媒体的长篇文章或报告,以及功能齐全的交互式应用程序。

每个这样的文档都表示为一个节点树中的一些节点可以有子节点,而其他的总是叶子节点。

为了说明这一点,考虑以下HTML文档:

<!DOCTYPE html>
<html class=e>
 <head><title>Aliens?</title></head>
 <body>Why yes.</body>
</html>

它表示如下:

请注意,由于HTML解析的神奇之处,并非所有ASCII空白字符都被转化为文本节点,但总体概念是清晰的。标记进入,节点输出。

可以使用非常棒的Live DOM Viewer来更详细地探索这个问题。

4.2. 节点树

节点是实现了实现Node的对象。节点参与一个称为节点树

实际上,你处理的是更具体的对象。

实现了实现Node的对象也实现了一个继承的接口:DocumentDocumentTypeDocumentFragmentElementCharacterDataAttr

实现了DocumentFragment的对象有时会实现ShadowRoot

实现了Element的对象通常也会实现一个继承的接口,例如HTMLAnchorElement

实现了CharacterData的对象也会实现一个继承的接口:TextProcessingInstructionComment

实现了Text的对象有时会实现CDATASection

因此,每个节点主要接口是以下之一:DocumentDocumentTypeDocumentFragmentShadowRootElementElement的一个继承接口,AttrTextCDATASectionProcessingInstructionComment

为简洁起见,本规范将实现了Node和继承接口NodeInterface的对象称为NodeInterface节点

节点树的限制如下,表示为节点及其潜在子节点之间的关系:

Document

树顺序

  1. 零个或多个ProcessingInstructionComment节点

  2. 可选地包含一个DocumentType节点

  3. 零个或多个ProcessingInstructionComment节点

  4. 可选地包含一个Element节点

  5. 零个或多个ProcessingInstructionComment节点

DocumentFragment
Element

零个或多个ElementCharacterData节点

DocumentType
CharacterData
Attr

没有子节点

Attr节点参与一个的历史原因;它们从不具有(非空)父节点或任何子节点,因此在一个中是孤立的。

要确定节点node长度,请执行以下步骤:

  1. 如果nodeDocumentTypeAttr节点,则返回0。

  2. 如果nodeCharacterData节点,则返回node数据长度

  3. 返回node子节点的数量。

如果节点长度为0,则该节点被视为空的

4.2.1. 文档树

文档树是一个节点树,其是一个文档

文档元素是一个文档中其父节点是该文档元素;如果不存在,则为 null。

根据节点树的限制,这样的元素只能有一个。

当一个节点文档时,该节点被认为是在文档树中

当一个节点被认为在文档中,它在文档树中术语在文档中不再被使用。它表明使用它的标准尚未更新,以考虑到影子树

4.2.2. 影子树

影子树是一个节点树,其是一个影子根

影子根总是通过其宿主附加到另一个节点树。因此,影子树永远不会是孤立的。影子根宿主节点树有时被称为光树

一个影子树的相应光树本身可以是一个影子树

当一个节点包含影子的根是一个文档时,该节点被认为是已连接的

4.2.2.1. 插槽

一个影子树包含零个或多个元素,它们是插槽

一个插槽只能通过HTML的slot元素创建。

一个插槽有一个关联的名称(一个字符串)。除非另有说明,否则它是空字符串。

使用这些属性更改步骤来更新一个插槽名称

  1. 如果element是一个插槽localNamename,且namespace为空,则:

    1. 如果valueoldValue,则返回。

    2. 如果value为null且oldValue为空字符串,则返回。

    3. 如果value为空字符串且oldValue为null,则返回。

    4. 如果value为null或空字符串,则将element名称设置为空字符串。

    5. 否则,将element名称设置为value

    6. 使用element运行为树分配可插槽对象

一个插槽是一个影子树中的第一个,在树顺序中,其名称为空字符串的插槽,有时被称为“默认插槽”。

一个插槽有一个关联的分配的节点(一个可插槽对象的列表)。除非另有说明,否则它是空的。

4.2.2.2. 可插槽对象

元素文本节点可插槽对象

插槽 可以是一个可插槽对象

一个可插槽对象有一个关联的名称(一个字符串)。除非另有说明,否则它是空字符串。

使用这些属性更改步骤来更新可插槽对象名称

  1. 如果localNameslotnamespace为空,则:

    1. 如果valueoldValue,则返回。

    2. 如果value为null且oldValue为空字符串,则返回。

    3. 如果value为空字符串且oldValue为null,则返回。

    4. 如果value为null或空字符串,则将element名称设置为空字符串。

    5. 否则,将element名称设置为value

    6. 如果element已分配,则为element已分配插槽运行分配可插槽对象

    7. element运行分配插槽

字母A 可插槽元素有一个关联的已分配插槽(null或插槽)。 除非另有说明,否则它为null。字母A 可插槽元素已分配的,如果它的已分配插槽非null。

一个可插槽对象有一个关联的手动插槽分配(null或插槽)。除非另有说明,否则它是null。

一个可插槽对象手动插槽分配可以使用对插槽的弱引用来实现,因为这个变量不能直接从脚本访问。

4.2.2.3. 查找插槽和可插槽对象

要为给定的可插槽对象slottable和一个可选的开放标志(除非另有说明,否则不设置)查找插槽,请执行以下步骤:

  1. 如果slottable父节点为null,则返回null。

  2. shadowslottable父节点影子根

  3. 如果shadow为null,则返回null。

  4. 如果开放标志被设置,且shadow模式不是“open”,则返回null。

  5. 如果shadow插槽分配为“manual”,则返回shadow后代中其手动分配节点包含slottable插槽,如果有的话;否则返回null。

  6. 返回shadow后代中第一个其名称slottable名称插槽,如果有的话;否则返回null。

要为给定的插槽slot查找可插槽对象,请执行以下步骤:

  1. result为空列表。

  2. rootslot

  3. 如果root不是影子根,则返回result

  4. hostroot宿主

  5. 如果root插槽分配为“manual”,则:

    1. result为« »。

    2. 对于每个可插槽对象slottable,在slot手动分配节点中,如果slottable父节点host,则slottable附加到result

  6. 否则,对于host的每个可插槽对象子节点slottable,按树顺序

    1. foundSlot查找插槽给定slottable的结果。

    2. 如果foundSlotslot,则slottable附加到result

  7. 返回result

要为给定的插槽slot查找扁平化可插槽对象,请执行以下步骤:

  1. result为空列表。

  2. 如果slot不是影子根,则返回result

  3. slottables查找可插槽对象给定slot的结果。

  4. 如果slottables为空列表,则将slot的每个可插槽对象子节点,按树顺序附加到slottables

  5. 对于slottables中的每个node

    1. 如果node是一个插槽,其是一个影子根,则:

      1. temporaryResult查找扁平化可插槽对象给定node的结果。

      2. 按顺序将temporaryResult中的每个可插槽对象附加到result

    2. 否则,将node附加到result

  6. 返回result

4.2.2.4. 分配可插槽对象和插槽

要为插槽slot 分配可插槽对象,请运行以下步骤:

  1. slottables查找可插槽对象给定slot的结果。

  2. 如果slottablesslot已分配节点不相同,则为slot发出插槽变更信号

  3. slot已分配节点设置为slottables

  4. 对于slottables中的每个slottable,将slottable已分配插槽设置为slot

要为给定节点root 分配树的可插槽对象,请按树顺序root包含后代中的每个插槽slot分配可插槽对象

要为给定可插槽对象slottable 分配插槽,请运行以下步骤:

  1. slot查找插槽给定slottable的结果。

  2. 如果slot不为null,则为slot运行分配可插槽对象

4.2.2.5. 发出插槽变更信号

每个相同来源窗口代理都有一个信号插槽集合中的一部分插槽),其初始值为空。[HTML]

要为插槽slot 发出插槽变更信号,请运行以下步骤:

  1. slot附加到slot相关代理信号插槽中。

  2. 排队一个变异观察者的微任务

4.2.3. 变异算法

要在将node插入parent中的child之前 确保预插入的有效性,请运行以下步骤:

  1. 如果parent不是DocumentDocumentFragmentElement节点,则抛出一个“HierarchyRequestErrorDOMException

  2. 如果nodeparent包含宿主的包容性祖先,则抛出一个“HierarchyRequestErrorDOMException

  3. 如果child不为null,且其父节点不是parent,则抛出一个“NotFoundErrorDOMException

  4. 如果node不是DocumentFragmentDocumentTypeElementCharacterData节点,则抛出一个“HierarchyRequestErrorDOMException

  5. 如果node是一个文本节点parent是一个文档,或node是一个文档类型,且parent不是文档,则抛出一个“HierarchyRequestErrorDOMException

  6. 如果parent是一个文档,且根据node实现的接口,下列语句中的任何一个为真,则抛出一个“HierarchyRequestErrorDOMException

    文档片段

    如果node有多个元素子节点,或有一个文本节点子节点

    否则,如果node有一个元素子节点,且parent有一个元素子节点child是一个文档类型,或者child不为null,且一个文档类型跟随child

    Element

    parent 有一个元素 子元素child是 一个文档类型,或者child非null,并且文档类型紧随child之后。

    DocumentType

    parent 有一个文档类型 子元素child非null, 并且一个元素先于child之前,或者child为null, 并且parent有一个元素 子元素

预插入 nodeparentchild之前,请运行以下步骤:

  1. 确保预插入的有效性 nodeparentchild之前。

  2. referenceChildchild

  3. 如果referenceChildnode,则将referenceChild设置为node下一个兄弟节点

  4. 插入nodeparentreferenceChild之前。

  5. 返回node

规范可以为所有或一些节点定义插入步骤。该算法将传递insertedNode,如下所示的插入算法。这些步骤不能修改insertedNode参与的节点树,创建浏览上下文触发事件,或以其他方式执行JavaScript。然而,这些步骤可以排队任务异步执行这些操作。

虽然插入步骤不能执行JavaScript(以及其他事情),但它们确实会产生脚本可观察到的后果。请考虑以下示例:

const h1 = document.querySelector('h1');

const fragment = new DocumentFragment();
const script = fragment.appendChild(document.createElement('script'));
const style = fragment.appendChild(document.createElement('style'));

script.innerText= 'console.log(getComputedStyle(h1).color)'; // Logs 'rgb(255, 0, 0)'
style.innerText = 'h1 {color: rgb(255, 0, 0);}';

document.body.append(fragment);

上例中的脚本记录了'rgb(255, 0, 0)',因为以下事件按顺序发生:

  1. 运行了插入算法,该算法会按顺序插入scriptstyle元素。

    1. HTML 标准的插入步骤script元素运行;它们什么都不做。[HTML]

    2. HTML 标准的插入步骤style元素运行;它们立即将其样式规则应用于文档。[HTML]

    3. HTML 标准的连接后步骤script元素运行;它们运行脚本,该脚本立即观察到上一步中应用的样式规则。[HTML]

规范也可以为所有或某些节点定义连接后步骤。该算法传递connectedNode,如下面的插入算法所示。

连接后步骤的目的是为节点提供机会执行任何与连接相关的操作,这些操作会修改connectedNode参与的节点树,创建浏览上下文,或执行其他 JavaScript。这些步骤允许一批节点相对于脚本原子地插入,所有主要的副作用都在批量插入到节点树完成后发生。这确保了所有待处理的节点树插入完全完成后才会发生更多的插入。

规范可以为所有或某些节点定义子节点变化步骤。该算法不传递参数,并在插入移除替换数据时调用。

要将节点插入到父节点中的子节点之前,并带有一个可选的抑制观察者标志,请运行以下步骤:

  1. 如果节点DocumentFragment节点,则将节点子节点赋值给nodes;否则赋值«节点»。

  2. nodes大小赋值给count

  3. 如果count为0,则返回。

  4. 如果节点DocumentFragment节点,则:

    1. 移除子节点并设置抑制观察者标志

    2. 节点排队一个树变更记录,包含«»、nodes、null和null。

      此步骤有意不关注抑制观察者标志

  5. 如果子节点非空,则:

    1. 对于每个活动范围,如果它的起始节点父节点起始偏移量大于子节点索引,则增加它的起始偏移量count

    2. 对于每个活动范围,如果它的结束节点父节点结束偏移量大于子节点索引,则增加它的结束偏移量count

  6. previousSibling赋值为子节点前一个兄弟节点或如果子节点为空,则赋值为父节点最后一个子节点

  7. 对于nodes中的每个节点,按树顺序

    1. 采用节点父节点节点文档中。

    2. 如果子节点为空,则将节点追加父节点子节点中。

    3. 否则,将节点插入到父节点子节点中,位于子节点索引之前。

    4. 如果父节点阴影宿主,其阴影根槽分配为"named",且节点可插槽的,则为节点分配一个槽

    5. 如果父节点阴影根,且父节点是一个,其已分配节点为空列表,则为父节点发出槽变更信号

    6. 运行为树分配可插槽,并使用节点

    7. 对于节点的每个包括阴影的包容性后代inclusiveDescendant,按包括阴影的树顺序

      1. 运行插入步骤,使用inclusiveDescendant

      2. 如果inclusiveDescendant已连接,则:

        1. 如果inclusiveDescendant自定义元素,则为inclusiveDescendant排队一个自定义元素回调反应,回调名称为"connectedCallback",参数列表为空。

        2. 否则,尝试升级inclusiveDescendant

          如果成功升级了inclusiveDescendant,则其connectedCallback将在升级元素算法期间自动排队。

  8. 如果抑制观察者标志未设置,则为父节点排队一个树变更记录,包含nodes、«»、previousSibling子节点

  9. 运行子节点变化步骤,针对父节点

  10. staticNodeList设置为列表,包含节点,初始值为«»。

    我们在调用任何一个节点的连接后步骤之前收集所有节点,而不是在遍历节点树时调用连接后步骤。这是因为连接后步骤可能会修改树的结构,使实时遍历不安全,可能导致在同一个节点上多次调用连接后步骤

  11. 对于nodes中的每个节点,按树顺序

    1. 对于节点的每个包括阴影的包容性后代inclusiveDescendant,按包括阴影的树顺序,将inclusiveDescendant追加到staticNodeList

  12. 对于每个节点staticNodeList,如果节点已连接,则使用节点运行连接后步骤

要将节点追加到父节点,请将节点预插入到父节点的空之前。

要用节点替换父节点内的子节点,请运行以下步骤:

  1. 如果父节点不是DocumentDocumentFragmentElement节点,则抛出一个"HierarchyRequestError"DOMException

  2. 如果节点父节点包含宿主的包容性祖先,则抛出一个"HierarchyRequestError"DOMException

  3. 如果子节点父节点不是父节点,则抛出一个"NotFoundError"DOMException

  4. 如果节点不是DocumentFragmentDocumentTypeElementCharacterData节点,则抛出一个"HierarchyRequestError"DOMException

  5. 如果节点文档,或文档类型,则抛出一个"HierarchyRequestError"DOMException

  6. 如果父节点文档,并且下面的某些语句为真,则抛出一个"HierarchyRequestError"DOMException

    DocumentFragment

    如果节点有多个元素子节点,或有一个文本节点子节点。

    否则,如果节点有一个元素子节点,并且父节点有一个不是子节点元素子节点,或者文档类型跟随子节点

    元素

    父节点有一个不是子节点元素子节点,或者文档类型跟随子节点

    文档类型

    父节点有一个文档类型子节点不是子节点,或者元素子节点之前。

    上面的语句与预插入算法不同。

  7. referenceChild赋值为子节点下一个兄弟节点

  8. 如果referenceChild节点,则将referenceChild设置为节点下一个兄弟节点

  9. previousSibling赋值为子节点前一个兄弟节点

  10. removedNodes赋值为空集。

  11. 如果子节点父节点非空,则:

    1. removedNodes设置为«子节点»。

    2. 移除子节点并设置抑制观察者标志

    上面的情况只有在子节点节点时为假。

  12. 如果节点DocumentFragment节点,则将节点子节点赋值给nodes;否则赋值«节点»。

  13. 插入节点父节点中,位于referenceChild之前,并设置抑制观察者标志

  14. 父节点排队一个树变更记录,包含nodesremovedNodespreviousSiblingreferenceChild

  15. 返回子节点

要在父节点内用节点替换全部,请运行以下步骤:

  1. removedNodes设置为父节点子节点

  2. addedNodes设置为空集。

  3. 如果节点DocumentFragment节点,则将节点子节点赋值给addedNodes

  4. 否则,如果节点非空,将addedNodes设置为«节点»。

  5. 移除父节点的所有子节点,按树顺序,并设置抑制观察者标志

  6. 如果节点非空,则将节点插入到父节点中的空之前,并设置抑制观察者标志

  7. 如果addedNodesremovedNodes非空,则为父节点排队一个树变更记录,包含addedNodesremovedNodes、null和null。

该算法不对节点树约束进行任何检查。规范作者需要明智地使用它。

要从父节点预先移除子节点,请运行以下步骤:

  1. 如果子节点父节点不是父节点,则抛出一个"NotFoundError"DOMException

  2. 移除子节点

  3. 返回子节点

规范可以为所有或某些节点定义移除步骤。该算法传递节点removedNode节点-或-nulloldParent,如下面的移除算法所示。

移除节点节点,并带有一个可选的抑制观察者标志,请运行以下步骤:

  1. 父节点赋值为节点父节点

  2. 断言:父节点非空。

  3. 索引赋值为节点索引

  4. 对于每个活动范围,如果其起始节点节点包容性后代,则将其起始设置为(父节点索引)。

  5. 对于每个活动范围,如果其结束节点节点包容性后代,则将其结束设置为(父节点索引)。

  6. 对于每个活动范围,如果其起始节点父节点,并且起始偏移量大于索引,则将其起始偏移量减 1。

  7. 对于每个活动范围,如果其结束节点父节点,并且结束偏移量大于索引,则将其结束偏移量减 1。

  8. 对于每个NodeIterator对象迭代器,其节点文档节点节点文档,运行NodeIterator预移除步骤,给定节点迭代器

  9. oldPreviousSibling设置为节点前一个兄弟节点

  10. oldNextSibling设置为节点下一个兄弟节点

  11. 移除节点父节点子节点中。

  12. 如果节点已分配,则为节点已分配槽运行分配可插槽

  13. 如果父节点阴影根,且父节点是一个,其已分配节点为空列表,则为父节点发出槽变更信号

  14. 如果节点有一个包容性后代,则:

    1. 运行为树分配可插槽,使用父节点

    2. 运行为树分配可插槽,使用节点

  15. 使用节点父节点运行移除步骤

  16. isParentConnected设置为父节点已连接

  17. 如果节点自定义元素,并且isParentConnected为真,则为节点排队一个自定义元素回调反应,回调名称为"disconnectedCallback",参数列表为空。

    目前有意不传递父节点自定义元素。如果有需要,将来可能会改变。

  18. 对于节点的每个包括阴影的后代descendant,按包括阴影的树顺序

    1. 使用descendant和null运行移除步骤

    2. 如果descendant自定义元素,并且isParentConnected为真,则为descendant排队一个自定义元素回调反应,回调名称为"disconnectedCallback",参数列表为空。

  19. 对于父节点的每个包容性祖先inclusiveAncestor,然后对于inclusiveAncestor已注册观察者列表中的每个registered,如果registered选项["subtree"]为真,则将新的临时已注册观察者追加到节点已注册观察者列表中。

  20. 如果抑制观察者标志未设置,则为父节点排队一个树变更记录,包含«»、«节点»、oldPreviousSiblingoldNextSibling

  21. 运行子节点变化步骤,针对父节点

4.2.4. 混入 NonElementParentNode

Web 兼容性阻止了 getElementById() 方法在元素上暴露(因此也不会暴露在ParentNode上)。

interface mixin NonElementParentNode {
  Element? getElementById(DOMString elementId);
};
Document includes NonElementParentNode;
DocumentFragment includes NonElementParentNode;
node . getElementById(elementId)

返回 node后代中第一个 元素,其 IDelementId

getElementById(elementId) 方法的步骤是返回 元素中第一个,其在树顺序中位于 this后代中,且其 IDelementId;否则,如果没有这样的元素,则返回 null。

class="heading settled" data-level="4.2.6" id="interface-parentnode">4.2.6. 混入 ParentNode

将节点转换为一个节点, 给定nodesdocument, 按以下步骤执行:

  1. node为null。

  2. 用一个新的Text节点替换nodes中的每个字符串, 其数据为字符串, 节点文档document

  3. 如果nodes包含一个节点, 则将node设置为nodes[0]。

  4. 否则, 将node设置为一个新的DocumentFragment节点, 其节点文档document, 然后追加每个nodes中的节点, 如果有的话,至该节点。

  5. 返回node

interface mixin ParentNode {
  [SameObject] readonly attribute HTMLCollection children;
  readonly attribute Element? firstElementChild;
  readonly attribute Element? lastElementChild;
  readonly attribute unsigned long childElementCount;

  [CEReactions, Unscopable] undefined prepend((Node or TrustedScript or DOMString)... nodes);
  [CEReactions, Unscopable] undefined append((Node or TrustedScript or DOMString)... nodes);
  [CEReactions, Unscopable] undefined replaceChildren((Node or TrustedScript or DOMString)... nodes);

  Element? querySelector(DOMString selectors);
  [NewObject] NodeList querySelectorAll(DOMString selectors);
};
Document includes ParentNode;
DocumentFragment includes ParentNode;
Element includes ParentNode;
collection=node. children
返回 元素
element=node. firstElementChild
返回第一个 元素;否则返回 null。
element=node. lastElementChild
返回最后一个 元素;否则返回 null。
node. prepend(nodes)

node 的第一个 子节点之前插入 nodes,同时将字符串替换为等效的 Text节点

抛出"HierarchyRequestError"DOMException,如果违反了 节点树的约束。

node. append(nodes)

node 的最后一个 子节点之后插入 nodes,同时将字符串替换为等效的 Text节点

抛出"HierarchyRequestError"DOMException,如果违反了 节点树的约束。

node. replaceChildren(nodes)

nodes 替换 node 的所有 子节点,同时将字符串替换为等效的 Text节点

抛出"HierarchyRequestError"DOMException,如果违反了 节点树的约束。

node. querySelector(selectors)

返回符合 selectors 的第一个 后代元素

node. querySelectorAll(selectors)

返回符合 selectors 的所有 后代元素

children 获取器步骤是返回一个 HTMLCollection集合,该集合以 为根,只匹配元素子节点

firstElementChild 获取器步骤是返回 第一个 子节点,该子节点是元素; 否则返回 null。

lastElementChild 获取器步骤是返回 最后一个子节点,该子节点是元素; 否则返回 null。

childElementCount 获取器步骤是返回 子节点的数量,只包含元素

prepend(nodes)方法的步骤为:

  1. node成为将节点转换为节点的结果,给定nodes节点文档

  2. 预插入node,在第一个子节点之前。

append(nodes)方法的步骤为:

  1. node成为将节点转换为节点的结果,给定nodes节点文档

  2. 追加node

replaceChildren(nodes)方法的步骤为:

  1. node成为将节点转换为节点的结果,给定nodes节点文档

  2. 确保预插入有效性node,在null之前。

  3. 替换所有节点为node内。

querySelector(selectors)方法的步骤是返回第一个运行范围匹配选择器字符串的结果,给定selectors,针对, 如果结果不是空列表,则返回结果; 否则为null。

querySelectorAll(selectors)方法的步骤是返回运行范围匹配选择器字符串静态结果,给定selectors,针对

4.2.7. 混入 NonDocumentTypeChildNode

Web 兼容性阻止了 previousElementSiblingnextElementSibling属性 在文档类型上公开(因此在 ChildNode上也不会公开)。

interfacemixinNonDocumentTypeChildNode {
   readonlyattributeElement? previousElementSibling;
   readonlyattributeElement? nextElementSibling;
};
ElementincludesNonDocumentTypeChildNode;
CharacterDataincludesNonDocumentTypeChildNode;
element=node. previousElementSibling
返回第一个 前面的兄弟,该兄弟是元素;否则返回 null。
element=node. nextElementSibling
返回第一个 后面的兄弟,该兄弟是元素;否则返回 null。

previousElementSibling获取器步骤是返回第一个 前面的兄弟,该兄弟是元素; 否则返回 null。

nextElementSibling获取器步骤是返回第一个 后面的兄弟,该兄弟是元素; 否则返回 null。

4.2.8. 混入 ChildNode

interfacemixinChildNode {
   [CEReactions,
   Unscopable] undefinedbefore((Node or DOMString)... nodes);
   [CEReactions,
   Unscopable] undefinedafter((Node or DOMString)... nodes);
   [CEReactions,
   Unscopable] undefinedreplaceWith((Node or DOMString)... nodes);
   [CEReactions,
   Unscopable] undefinedremove();
};
DocumentTypeincludesChildNode;
ElementincludesChildNode;
CharacterDataincludesChildNode;
node. before(...nodes)

node之前插入nodes, 同时将nodes中的字符串替换为等效的 Text节点

抛出 "HierarchyRequestError" DOMException 如果违反了 节点树的约束。

node. after(...nodes)

node之后插入nodes, 同时将nodes中的字符串替换为等效的 Text节点

抛出 "HierarchyRequestError" DOMException 如果违反了 节点树的约束。

node. replaceWith(...nodes)

nodes替换node, 同时将nodes中的字符串替换为等效的 Text节点

抛出 "HierarchyRequestError" DOMException 如果违反了 节点树的约束。

node. remove()
移除node

before(nodes) 方法的步骤为:

  1. parent成为父节点

  2. 如果parent为 null,则返回。

  3. viablePreviousSibling成为的第一个不在nodes中的前面的兄弟节点;否则为 null。

  4. node成为将节点转换为节点的结果,给定nodes节点文档

  5. 如果viablePreviousSibling为 null,则将其设置为parent第一个子节点;否则将其设置为viablePreviousSibling下一个兄弟节点

  6. 预插入nodeparent,在viablePreviousSibling之前。

after(nodes) 方法的步骤为:

  1. parent成为父节点

  2. 如果parent为 null,则返回。

  3. viableNextSibling成为的第一个不在nodes中的后面的兄弟节点;否则为 null。

  4. node成为将节点转换为节点的结果,给定nodes节点文档

  5. 预插入nodeparent,在viableNextSibling之前。

replaceWith(nodes) 方法的步骤为:

  1. parent成为父节点

  2. 如果parent为 null,则返回。

  3. viableNextSibling成为的第一个不在nodes中的后面的兄弟节点;否则为 null。

  4. node成为将节点转换为节点的结果,给定nodes节点文档

  5. 如果父节点parent, 则替换nodeparent内。

    可能已被插入node

  6. 否则, 预插入nodeparent,在viableNextSibling之前。

remove() 方法的步骤为:

  1. 如果父节点为 null,则返回。

  2. 移除

4.2.9. 混入 Slottable

interface mixin Slottable {
  readonly attribute HTMLSlotElement? assignedSlot;
};
Element includes Slottable;
Text includes Slottable;

assignedSlot 获取器的步骤是返回给定查找插槽的结果,前提是设置了open flag

4.2.10. 旧式集合:NodeListHTMLCollection

集合是表示节点列表的对象。集合可以是实时集合静态集合。除非另有说明,集合必须是实时集合

如果集合实时集合,那么该对象上的属性和方法必须操作实际的底层数据,而不是数据的快照。

集合创建时,会与其关联一个过滤器和根。

然后,集合 表示以集合的根为根的子树的视图,仅包含符合给定过滤器的节点。该视图是线性的。在没有特定要求的情况下,集合中的节点必须按树顺序排序。

4.2.10.1. 接口 NodeList

NodeList 对象是集合的一部分,表示节点的列表。

[Exposed=Window]
interface NodeList {
  getter Node? item(unsigned long index);
  readonly attribute unsigned long length;
  iterable<Node>;
};
collection . length
返回节点的数量,位于集合中。
element = collection . item(index)
element = collection[index]
返回具有索引index节点,来自集合中。这些节点树顺序排序。

对象的支持的属性索引是从零到节点数量减一的范围内的数字由集合表示。如果没有这样的元素,那么就没有支持的属性索引

length属性必须返回由集合表示的节点数量。

item(index)方法必须返回集合中第index节点。如果集合中没有第index节点,则该方法必须返回null。

4.2.10.2. 接口HTMLCollection
[Exposed=Window, LegacyUnenumerableNamedProperties]
interface HTMLCollection {
  readonly attribute unsigned long length;
  getter Element? item(unsigned long index);
  getter Element? namedItem(DOMString name);
};

HTMLCollection对象是集合的一个元素

HTMLCollection是一个我们无法从网络中消除的历史遗留物。当然,开发人员可以继续使用它,但新API标准的设计者不应再使用它(在IDL中使用sequence<T>代替)。

collection . length
返回元素的数量,位于集合中。
element = collection . item(index)
element = collection[index]
返回集合中索引为index元素。这些元素树顺序排序。
element = collection . namedItem(name)
element = collection[name]
返回集合中第一个具有ID或名称为name元素

对象的支持的属性索引是从零到元素数量减一的范围内的数字由集合表示。如果没有这样的元素,那么就没有支持的属性索引

length获取器步骤应返回由集合表示的节点数量。

item(index)方法步骤应返回集合中第index元素。如果集合中没有第index元素,则该方法必须返回null。

支持的属性名称是通过以下步骤返回的列表中的值:

  1. result为一个空列表。

  2. 对于集合中由集合表示的每个element,按树顺序处理:

    1. 如果element具有一个不在result中的ID,则将elementID添加到result中。

    2. 如果element位于HTML命名空间中,并且具有一个name属性,且其既不是空字符串也不在result中,则将elementname属性的值添加到result中。

  3. 返回result

namedItem(key)方法步骤是:

  1. 如果key是空字符串,返回null。

  2. 返回集合中第一个满足以下任一条件的元素

    • IDkey
    • 它位于HTML命名空间中,并且具有一个name属性,且其值为key

    如果没有这样的元素,则返回null。

4.3. Mutation observers

每个相同来源窗口代理都有一个突变观察者微任务排队(布尔值),其初始值为false。[HTML]

每个相同来源窗口代理还具有待处理的突变观察者(一个包含零个或多个MutationObserver对象的集合),其初始状态为空。

排队一个突变观察者微任务,请执行以下步骤:

  1. 如果周围代理突变观察者微任务排队为true,则返回。

  2. 周围代理突变观察者微任务排队设置为true。

  3. 排队一个微任务通知突变观察者

通知突变观察者,请执行以下步骤:

  1. 周围代理突变观察者微任务排队设置为false。

  2. notifySet周围代理待处理的突变观察者的克隆。

  3. 清空周围代理待处理的突变观察者

  4. signalSet周围代理信号槽列表的克隆。

  5. 清空周围代理信号槽列表

  6. 对于notifySet中的每个mo

    1. recordsmo记录队列的克隆。

    2. 清空mo记录队列

    3. 对于mo节点列表中的每个node移除所有其观察者mo瞬态注册观察者,从node注册观察者列表中。

    4. 如果records不为空,则使用«recordsmo»和“report”作为参数,并将回调的this值设置为mo调用mo回调

  7. 对于signalSet中的每个slot触发一个名为slotchange的事件,其bubbles属性设置为true,在slot处。


每个节点都有一个注册观察者列表(一个包含零个或多个注册观察者列表),其初始状态为空。

一个注册观察者由一个观察者(一个MutationObserver对象)和选项(一个MutationObserverInit字典)组成。

一个瞬态注册观察者是一个注册观察者,它还包括一个(一个注册观察者)。

瞬态注册观察者用于跟踪给定节点后代中的突变,在节点被移除后,以便在其父节点上将subtree设置为true时,不会丢失这些突变。

4.3.1. 接口 MutationObserver

[Exposed=Window]
interface MutationObserver {
  constructor(MutationCallback callback);

  undefined observe(Node target, optional MutationObserverInit options = {});
  undefined disconnect();
  sequence<MutationRecord> takeRecords();
};

callback MutationCallback = undefined (sequence<MutationRecord> mutations, MutationObserver observer);

dictionary MutationObserverInit {
  boolean childList = false;
  boolean attributes;
  boolean characterData;
  boolean subtree = false;
  boolean attributeOldValue;
  boolean characterDataOldValue;
  sequence<DOMString> attributeFilter;
};

MutationObserver 对象可用于观察 节点 的变动。

每个 MutationObserver 对象有以下关联概念:

observer = new MutationObserver(callback)
构造一个 MutationObserver 对象,并将其 回调 设置为 callback。在 observe() 方法注册的 节点 变动后,调用 callback,传入一个 MutationRecord 对象的列表作为第一个参数,并将构造的 MutationObserver 对象作为第二个参数。
observer . observe(target, options)
指示用户代理观察给定的 target(一个 节点)并根据 options(一个对象)提供的条件报告任何变动。

options 参数允许通过对象成员设置变动观察选项。以下是可以使用的对象成员:

childList
如果要观察 target子节点 的变动,则设置为 true。
attributes
如果要观察 target属性 的变动,则设置为 true。如果指定了 attributeOldValueattributeFilter,则可以省略。
characterData
如果要观察 target数据 的变动,则设置为 true。如果指定了 characterDataOldValue,则可以省略。
subtree
如果要观察不仅是 target,而且还有 target后代节点 的变动,则设置为 true。
attributeOldValue
如果 attributes 为 true 或省略,并且需要记录变动前 target属性 ,则设置为 true。
characterDataOldValue
如果 characterData 设置为 true 或省略,并且需要记录变动前 target数据,则设置为 true。
attributeFilter
如果不需要观察所有 属性 的变动,并且 attributes 为 true 或省略,则设置为 属性的本地名称(不包括 命名空间)的列表。
observer . disconnect()
停止 observer 观察任何变动。在再次使用 observe() 方法之前,observer回调 将不会被调用。
observer . takeRecords()
清空 记录队列 并返回其中的内容。

new MutationObserver(callback) 构造函数的步骤是将 this回调 设置为 callback

observe(target, options) 方法的步骤如下:

  1. 如果 options["attributeOldValue"] 或 options["attributeFilter"] 存在,且 options["attributes"] 不 存在,则将 options["attributes"] 设置为 true。

  2. 如果 options["characterDataOldValue"] 存在,且 options["characterData"] 不 存在,则将 options["characterData"] 设置为 true。

  3. 如果 options["childList"]、options["attributes"] 和 options["characterData"] 都不为 true,则 抛出 TypeError

  4. 如果 options["attributeOldValue"] 为 true,而 options["attributes"] 为 false,则 抛出 TypeError

  5. 如果 options["attributeFilter"] 存在,而 options["attributes"] 为 false,则 抛出 TypeError

  6. 如果 options["characterDataOldValue"] 为 true,而 options["characterData"] 为 false,则 抛出 TypeError

  7. 对于 target注册观察者列表 中的每个 registered,如果 registered观察者this

    1. 对于 this节点列表 中的每个 node移除所有 临时注册观察者,其 来源registered,从 node注册观察者列表 中移除。

    2. registered选项 设置为 options

  8. 否则:

    1. 追加一个新的 注册观察者,其 观察者this,并将 选项 设置为 options,追加到 target注册观察者列表

    2. 追加一个指向 target 的弱引用到 this节点列表 中。

disconnect() 方法的步骤如下:

  1. 对于 this节点列表 中的每个 node移除任何 注册观察者,如果 this 是该 观察者

  2. 清空 this记录队列

takeRecords() 方法的步骤如下:

  1. this记录队列 克隆records

  2. 清空 this记录队列

  3. 返回 records

4.3.2. 排队突变记录

要为 typetargetnamenamespaceoldValueaddedNodesremovedNodespreviousSiblingnextSibling 排队一个突变记录,请执行以下步骤:

  1. interestedObservers 成为一个空的 映射

  2. nodes 成为 target包括的祖先

  3. 对于 nodes 中的每个 node,然后 对每个 node注册观察者列表 中的 registered

    1. options 成为 registered选项

    2. 如果以下条件都不成立

      则:

      1. mo 成为 registered观察者

      2. 如果 interestedObservers[mo] 不 存在,则 interestedObservers[mo] 设置为 null。

      3. 如果 type 是 "attributes" 并且 options["attributeOldValue"] 为 true,或 type 是 "characterData" 并且 options["characterDataOldValue"] 为 true,则 interestedObservers[mo] 设置为 oldValue

  4. 对于 interestedObservers 中的每个 observermappedOldValue

    1. record 成为一个新的 MutationRecord 对象,其 type 设置为 typetarget 设置为 targetattributeName 设置为 nameattributeNamespace 设置为 namespaceoldValue 设置为 mappedOldValueaddedNodes 设置为 addedNodesremovedNodes 设置为 removedNodespreviousSibling 设置为 previousSiblingnextSibling 设置为 nextSibling

    2. record 加入到 observer记录队列 中。

    3. observer 追加到 周围代理待处理突变观察者 中。

  5. 排队一个突变观察者微任务

要为 target 以及 addedNodesremovedNodespreviousSiblingnextSibling 排队一个树突变记录,请执行以下步骤:

  1. 断言:addedNodesremovedNodes 非空

  2. 排队一个突变记录类型为 "childList",目标为 target,值为 null、null、null、addedNodesremovedNodespreviousSiblingnextSibling

4.3.3. 接口 MutationRecord

[Exposed=Window]
interface MutationRecord {
  readonly attribute DOMString type;
  [SameObject] readonly attribute Node target;
  [SameObject] readonly attribute NodeList addedNodes;
  [SameObject] readonly attribute NodeList removedNodes;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;
  readonly attribute DOMString? attributeName;
  readonly attribute DOMString? attributeNamespace;
  readonly attribute DOMString? oldValue;
};
record . type
如果是 属性 突变,返回 "attributes"。 如果是 CharacterData 节点 的突变,返回 "characterData"。如果是 节点 突变,返回 "childList"。
record . target
返回突变影响的 节点,具体取决于 type。 对于 "attributes",返回其 元素属性 发生了变化。对于 "characterData",返回 CharacterData 节点。对于 "childList",返回其 子节点 发生变化的 节点
record . addedNodes
record . removedNodes
分别返回添加和移除的 节点
record . previousSibling
record . nextSibling
分别返回添加或移除的 节点前一个下一个 兄弟节点;否则返回 null。
record . attributeName
返回已更改的 属性 的本地名称;否则返回 null。
record . attributeNamespace
返回已更改的 属性的命名空间;否则返回 null。
record . oldValue
返回值取决于 type。 对于 "attributes",返回更改前的 属性值。 对于 "characterData",返回更改前的 节点数据。对于 "childList",返回 null。

typetargetaddedNodesremovedNodespreviousSiblingnextSiblingattributeNameattributeNamespaceoldValue 属性必须返回其初始化时的值。

4.4. 接口 Node

[Exposed=Window]
interface Node : EventTarget {
  const unsigned short ELEMENT_NODE = 1;
  const unsigned short ATTRIBUTE_NODE = 2;
  const unsigned short TEXT_NODE = 3;
  const unsigned short CDATA_SECTION_NODE = 4;
  const unsigned short ENTITY_REFERENCE_NODE = 5; // legacy
  const unsigned short ENTITY_NODE = 6; // legacy
  const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
  const unsigned short COMMENT_NODE = 8;
  const unsigned short DOCUMENT_NODE = 9;
  const unsigned short DOCUMENT_TYPE_NODE = 10;
  const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
  const unsigned short NOTATION_NODE = 12; // legacy
  readonly attribute unsigned short nodeType;
  readonly attribute DOMString nodeName;

  readonly attribute USVString baseURI;

  readonly attribute boolean isConnected;
  readonly attribute Document? ownerDocument;
  Node getRootNode(optional GetRootNodeOptions options = {});
  readonly attribute Node? parentNode;
  readonly attribute Element? parentElement;
  boolean hasChildNodes();
  [SameObject] readonly attribute NodeList childNodes;
  readonly attribute Node? firstChild;
  readonly attribute Node? lastChild;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;

  [CEReactions] attribute DOMString? nodeValue;
  [CEReactions] attribute DOMString? textContent;
  [CEReactions] undefined normalize();

  [CEReactions, NewObject] Node cloneNode(optional boolean deep = false);
  boolean isEqualNode(Node? otherNode);
  boolean isSameNode(Node? otherNode); // legacy alias of ===

  const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
  const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
  const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
  const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
  const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
  const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
  unsigned short compareDocumentPosition(Node other);
  boolean contains(Node? other);

  DOMString? lookupPrefix(DOMString? namespace);
  DOMString? lookupNamespaceURI(DOMString? prefix);
  boolean isDefaultNamespace(DOMString? namespace);

  [CEReactions] Node insertBefore(Node node, Node? child);
  [CEReactions] Node appendChild(Node node);
  [CEReactions] Node replaceChild(Node node, Node child);
  [CEReactions] Node removeChild(Node child);
};

dictionary GetRootNodeOptions {
  boolean composed = false;
};

Node 是一个用于所有节点的抽象接口。你不能直接获取它的实例。

每个节点都有一个相关的 节点文档,在创建时设置,为文档

可以通过节点节点文档更改adopt算法。

给定一个event时,节点get the parent 算法返回已分配插槽,如果节点分配了;否则,返回父节点

每个节点也有一个注册观察者列表


node . nodeType

返回一个与node类型相对应的数字,如下所示:

Element
Node . ELEMENT_NODE (1)。
Attr
Node . ATTRIBUTE_NODE (2)。
一个独占的Text节点
Node . TEXT_NODE (3)。
CDATASection
Node . CDATA_SECTION_NODE (4)。
ProcessingInstruction
Node . PROCESSING_INSTRUCTION_NODE (7)。
Comment
Node . COMMENT_NODE (8)。
Document
Node . DOCUMENT_NODE (9)。
DocumentType
Node . DOCUMENT_TYPE_NODE (10)。
DocumentFragment
Node . DOCUMENT_FRAGMENT_NODE (11)。
node . nodeName

返回一个与node类型相对应的字符串,如下所示:

Element
它的HTML大写的限定名称
Attr
它的限定名称
一个独占的Text节点
"#text"。
CDATASection
"#cdata-section"。
ProcessingInstruction
它的目标
Comment
"#comment"。
Document
"#document"。
DocumentType
它的名称
DocumentFragment
"#document-fragment"。

nodeType 的 getter 步骤是返回第一个匹配的语句,切换接口 this implements

Element
ELEMENT_NODE (1)
Attr
ATTRIBUTE_NODE (2);
一个 独占 Text 节点
TEXT_NODE (3);
CDATASection
CDATA_SECTION_NODE (4);
ProcessingInstruction
PROCESSING_INSTRUCTION_NODE (7);
Comment
COMMENT_NODE (8);
Document
DOCUMENT_NODE (9);
DocumentType
DOCUMENT_TYPE_NODE (10);
DocumentFragment
DOCUMENT_FRAGMENT_NODE (11).

nodeName 的 getter 步骤是返回第一个匹配的语句,切换接口 this implements

Element
它的 HTML 大写限定名称
Attr
它的 限定名称
一个 独占 Text 节点
"#text"。
CDATASection
"#cdata-section"。
ProcessingInstruction
它的 目标
Comment
"#comment"。
Document
"#document"。
DocumentType
它的 名称
DocumentFragment
"#document-fragment"。

node . baseURI
返回 node节点文档文档基础 URL

baseURI 的 getter 步骤是返回 this节点文档文档基础 URL,并且序列化


node . isConnected

如果 node连接的,则返回 true;否则返回 false。

node . ownerDocument
返回 node document。 对于文档,返回 null。
node . getRootNode()
返回 node
node . getRootNode({ composed:true })
返回 node包含 shadow 的根
node . parentNode
返回父节点
node . parentElement
返回父元素
node . hasChildNodes()
返回 node 是否有子节点
node . childNodes
返回子节点
node . firstChild
返回第一个子节点
node . lastChild
返回最后一个子节点
node . previousSibling
返回前一个兄弟节点
node . nextSibling
返回下一个兄弟节点

isConnected 的 getter 步骤是如果 this连接的,则返回 true;否则返回 false。

ownerDocument 的 getter 步骤是如果 this文档,则返回 null;否则返回 this节点文档

一个 文档节点文档 就是该 文档 本身。所有 节点始终都有一个 节点文档

getRootNode(options) 方法步骤是如果 options["composed"] 为 true,则返回 this包括影子的根;否则返回 this

parentNode 的 getter 步骤是返回 this父级

parentElement 的 getter 步骤是返回 this父元素

hasChildNodes() 方法步骤是如果 this子节点,则返回 true;否则返回 false。

childNodes 的 getter 步骤是返回一个 NodeList,其根位于 this 处,仅匹配 子节点

firstChild 的 getter 步骤是返回 this第一个子节点

lastChild 的 getter 步骤是返回 this最后一个子节点

previousSibling 的 getter 步骤是返回 this上一个兄弟节点

nextSibling 的 getter 步骤是返回 this下一个兄弟节点


nodeValue 的 getter 步骤是返回以下内容,切换接口 this implements

Attr
this
CharacterData
this数据
否则
Null。

nodeValue 的 setter 步骤是,如果给定的值为 null,则将其视为空字符串,然后按以下描述执行,切换接口 this implements

Attr

设置现有属性值,使用 this 和给定的值。

CharacterData

替换数据,使用节点 this,偏移量 0,计数 this长度,以及数据给定的值。

否则

什么也不做。

获取文本内容,使用 节点 node,返回以下内容,切换接口 node implements

DocumentFragment
Element
node后代文本内容
Attr
node
CharacterData
node数据
否则
Null。

textContent 的 getter 步骤是返回运行 获取文本内容 的结果,使用 this

字符串替换全部,使用一个字符串 string节点 parent 内,运行以下步骤:

  1. node 为 null。

  2. 如果 string 不是空字符串,则将 node 设置为一个新的 Text 节点,其 数据string节点文档parent节点文档

  3. 全部替换,使用 nodeparent 内。

设置文本内容,使用一个 节点 node 和一个字符串 value,按下述定义操作,切换接口 node implements

DocumentFragment
Element

字符串替换全部,使用 valuenode 内。

Attr

设置现有属性值,使用 nodevalue

CharacterData

替换数据,使用节点 node,偏移量 0,计数 node长度,以及数据 value

否则

什么也不做。

textContent 的 setter 步骤是,如果给定的值为 null,则将其视为空字符串,然后运行 设置文本内容,使用 this 和给定的值。


node . normalize()
移除 独占 Text 节点,并将剩余 数据连接到它们的第一个 节点中。

方法 normalize() 的步骤是针对 后代 独占 Text 节点 node 运行这些步骤:

  1. lengthnode长度
  2. 如果 length 为零,则 移除 node 并继续下一个 独占 Text 节点(如果有的话)。
  3. datanode数据与其 连续的独占 Text 节点(不包括其自身)的 连接,按 树顺序
  4. 用节点 node,偏移量 length,计数 0 和数据 data 替换数据
  5. currentNodenode下一个兄弟节点
  6. currentNode 是一个 独占 Text 节点 时:

    1. 对于起始节点是 currentNode 的每个 活动范围,将 length 加到其 起始偏移量 并将其 起始节点 设置为 node

    2. 对于结束节点是 currentNode 的每个 活动范围,将 length 加到其 结束偏移量 并将其 结束节点 设置为 node

    3. 对于起始节点是 currentNode父级且起始偏移量是 currentNode索引 的每个活动范围,将其起始节点设置为 node,并将其起始偏移量设置为 length

    4. 对于结束节点是 currentNode父级且结束偏移量是 currentNode索引 的每个活动范围,将其结束节点设置为 node,并将其结束偏移量设置为 length

    5. currentNode长度 加到 length 中。

    6. currentNode 设置为其下一个兄弟节点。

  7. 移除 node连续独占 Text 节点(不包括其自身),按树顺序。

node . cloneNode([deep = false])
返回 node 的副本。如果 deep 为 true,副本还包括 node后代
node . isEqualNode(otherNode)
返回 nodeotherNode 是否具有相同的属性。

规范可能会为所有或部分 节点定义克隆步骤。该算法会传递 copynodedocument 和一个可选的克隆子节点标志,如在 克隆算法中所指示的。

HTML 为 scriptinput元素定义了克隆步骤。SVG 也应为其script元素做同样的事情,但目前尚未提到。

克隆一个node,可选地带上document克隆子节点标志,请运行以下步骤:

  1. 如果没有给出document,则令documentnode节点文档

  2. 如果node是一个元素,则:

    1. copy创建元素的结果,给定documentnode本地名称node命名空间node命名空间前缀nodeis,并且取消同步自定义元素标志

    2. 对于node属性列表中的每个attribute

      1. copyAttributeattribute克隆

      2. copyAttribute附加到copy

  3. 否则,令copy为一个节点,该节点实现node相同的接口,并满足以下额外要求,基于node实现的接口进行切换:

    Document

    copy编码内容类型URL类型模式设置为node的对应值。

    DocumentType

    copy名称公共ID系统ID设置为node的对应值。

    Attr

    copy命名空间命名空间前缀本地名称设置为node的对应值。

    Text
    Comment

    copy数据设置为node的对应值。

    ProcessingInstruction

    copy目标数据设置为node的对应值。

    否则

    不做任何操作。

  4. 设置copy节点文档documentcopy,如果copy是一个文档,否则将copy节点文档设置为document

  5. 运行任何在其他适用规范中为node定义的克隆步骤,并传递copynodedocument,以及如果设置了克隆子节点标志,则将其作为参数。

  6. 如果设置了克隆子节点标志,则对于node的每个子节点,按树顺序:将克隆子节点的结果(带有document克隆子节点标志设置)附加copy

  7. 如果node是一个影宿主,且其影根可克隆性为真:

    1. 断言:copy不是一个影宿主

    2. 运行附加影根,使用copynode影根模式、真、node影根可序列化性node影根焦点委派,以及node影根插槽分配

    3. copy影根声明性设置为node影根声明性

    4. 对于node影根的每个子节点,按树顺序:将克隆子节点的结果(带有document克隆子节点标志设置)附加copy影根

  8. 返回copy

方法cloneNode(deep)的步骤如下:

  1. 如果this是一个影根,则抛出"NotSupportedError"DOMException

  2. 返回克隆this,如果deep为 true,则设置克隆子节点标志

如果以下所有条件都为真,则节点A等于节点B

方法isEqualNode(otherNode)的步骤是:如果otherNode非空并且this等于otherNode,则返回 true;否则返回 false。

方法isSameNode(otherNode)的步骤是:如果otherNodethis,则返回 true;否则返回 false。


node . compareDocumentPosition(other)
返回一个位掩码,指示other相对于node的位置。可以设置以下位:
Node . DOCUMENT_POSITION_DISCONNECTED (1)
nodeother不在同一中时设置。
Node . DOCUMENT_POSITION_PRECEDING (2)
othernode之前preceding时设置。
Node . DOCUMENT_POSITION_FOLLOWING (4)
othernode之后following时设置。
Node . DOCUMENT_POSITION_CONTAINS (8)
othernode祖先时设置。
Node . DOCUMENT_POSITION_CONTAINED_BY (16, 16 的十六进制表示为 10)
othernode后代时设置。
node . contains(other)
如果othernode包容后代,则返回 true;否则返回 false。

以下是compareDocumentPosition()返回的掩码常量:

方法compareDocumentPosition(other)的步骤如下:

  1. 如果thisother,则返回零。

  2. node1设为othernode2设为this

  3. attr1attr2设为 null。

  4. 如果node1是一个属性,则将attr1设为node1,并将node1设为attr1元素

  5. 如果node2是一个属性,则:

    1. attr2设为node2,并将node2设为attr2元素

    2. 如果attr1node1非空,且node2node1,则:

      1. 对于node2属性列表中的每个attr

        1. 如果attr等于attr1,则返回DOCUMENT_POSITION_IMPLEMENTATION_SPECIFICDOCUMENT_POSITION_PRECEDING之和。

        2. 如果attr等于attr2,则返回DOCUMENT_POSITION_IMPLEMENTATION_SPECIFICDOCUMENT_POSITION_FOLLOWING之和。

  6. 如果node1node2为 null,或者node1node2不同,则返回DOCUMENT_POSITION_DISCONNECTEDDOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC,以及DOCUMENT_POSITION_PRECEDINGDOCUMENT_POSITION_FOLLOWING之和,确保返回值一致。

    是否返回DOCUMENT_POSITION_PRECEDINGDOCUMENT_POSITION_FOLLOWING通常是通过指针比较实现的。在JavaScript实现中,可以使用缓存的Math.random()值。

  7. 如果node1node2祖先,并且attr1为 null,或node1node2attr2非空,则返回DOCUMENT_POSITION_CONTAINSDOCUMENT_POSITION_PRECEDING之和。

  8. 如果node1node2后代,并且attr2为 null,或node1node2attr1非空,则返回DOCUMENT_POSITION_CONTAINED_BYDOCUMENT_POSITION_FOLLOWING之和。

  9. 如果node1node2之前preceding,则返回DOCUMENT_POSITION_PRECEDING

    由于该算法处理属性的方式,导致节点属性被认为在该节点之前,尽管属性参与同一

  10. 返回DOCUMENT_POSITION_FOLLOWING

方法contains(other)的步骤是:如果other包容后代,则返回 true;否则(包括other为 null 时)返回 false。


要为一个使用namespaceelement 定位命名空间前缀,请执行以下步骤:

  1. 如果element命名空间namespace,且其命名空间前缀非空,则返回其命名空间前缀

  2. 如果element具有一个属性,其命名空间前缀是"xmlns"且namespace,则返回element的第一个此类属性本地名称

  3. 如果element父元素不为 null,则返回在该元素上使用namespace运行定位命名空间前缀的结果。

  4. 返回 null。

要为一个node使用prefix 定位命名空间,请根据node 实现的接口进行切换:

Element
  1. 如果prefix是"xml",则返回XML 命名空间

  2. 如果prefix是"xmlns",则返回XMLNS 命名空间

  3. 如果其命名空间非空,且其命名空间前缀prefix,则返回命名空间

  4. 如果它具有一个属性,该属性的命名空间XMLNS 命名空间命名空间前缀为"xmlns",且本地名称prefix,或者如果prefix为 null,且它具有一个属性,其命名空间XMLNS 命名空间命名空间前缀为 null,且本地名称为"xmlns",则返回其(如果值不是空字符串),否则返回 null。

  5. 如果其父元素为 null,则返回 null。

  6. 返回在其父元素上使用prefix运行定位命名空间的结果。

Document
  1. 如果其文档元素为 null,则返回 null。

  2. 返回在其文档元素上使用prefix运行定位命名空间的结果。

DocumentType
DocumentFragment

返回 null。

Attr
  1. 如果其元素为 null,则返回 null。

  2. 返回在其元素上使用prefix运行定位命名空间的结果。

否则
  1. 如果其父元素为 null,则返回 null。

  2. 返回在其父元素上使用prefix运行定位命名空间的结果。

方法lookupPrefix(namespace)的步骤如下:

  1. 如果 namespace 为 null 或空字符串,则返回 null。

  2. 根据接口 实现的类型进行判断:

    Element

    返回定位命名空间前缀的结果,使用namespace针对

    Document
    1. 如果文档元素为 null,则返回 null。

    2. 返回定位命名空间前缀的结果,使用namespace针对文档元素

    DocumentType
    DocumentFragment
    返回 null。
    Attr
    1. 如果元素为 null,则返回 null。

    2. 返回定位命名空间前缀的结果,使用namespace针对元素

    Otherwise
    1. 如果父元素为 null,则返回 null。

    2. 返回定位命名空间前缀的结果,使用namespace针对父元素

方法lookupNamespaceURI(prefix)的步骤如下:

  1. 如果prefix是空字符串,则将其设置为 null。

  2. 返回使用prefixthis上运行定位命名空间的结果。

方法isDefaultNamespace(namespace)的步骤如下:

  1. 如果namespace是空字符串,则将其设置为 null。

  2. defaultNamespace为使用 null 在this上运行定位命名空间的结果。

  3. 如果defaultNamespacenamespace相同,则返回 true;否则返回 false。


方法insertBefore(node, child)的步骤是返回将node插入到this之前child预插入结果。

方法appendChild(node)的步骤是返回将node追加到this追加结果。

方法replaceChild(node, child)的步骤是返回在this内用node替换child的结果。

方法removeChild(child)的步骤是返回从this预删除child的结果。


对于root节点具有限定名称qualifiedName的元素列表是通过以下算法返回的HTMLCollection

  1. 如果qualifiedName是U+002A (*),则返回一个根为rootHTMLCollection,其过滤器仅匹配后代元素

  2. 否则,如果root节点文档是一个HTML 文档,则返回一个根为rootHTMLCollection,其过滤器匹配以下后代元素

  3. 否则,返回一个根为rootHTMLCollection,其过滤器匹配后代元素,其限定名称qualifiedName

当使用相同参数调用时,只要root节点文档类型未更改,可能会返回与之前调用返回的相同的HTMLCollection对象。

对于root节点具有命名空间namespace和本地名称localName的元素列表是通过以下算法返回的HTMLCollection

  1. 如果namespace是空字符串,则将其设置为 null。

  2. 如果namespacelocalName均为 U+002A (*),则返回一个根为rootHTMLCollection,其过滤器匹配后代元素

  3. 如果namespace是U+002A (*),则返回一个根为rootHTMLCollection,其过滤器匹配后代元素,其本地名称localName

  4. 如果localName是U+002A (*),则返回一个根为rootHTMLCollection,其过滤器匹配后代元素,其命名空间namespace

  5. 返回一个根为rootHTMLCollection,其过滤器匹配后代元素,其命名空间namespace本地名称localName

当使用相同参数调用时,可能会返回与之前调用返回的相同的HTMLCollection对象。

对于root节点具有类名classNames的元素列表是通过以下算法返回的HTMLCollection

  1. classes为在classNames上运行有序集解析器的结果。
  2. 如果classes为空集,则返回一个空的HTMLCollection
  3. 返回一个根为rootHTMLCollection,其过滤器匹配后代元素,这些元素的所有都在classes中。

    对于的比较,如果root节点文档模式为"quirks",则必须以ASCII 大小写不敏感的方式进行比较;否则以相同的方式进行比较。

当使用相同参数调用时,可能会返回与之前调用返回的相同的HTMLCollection对象。

4.5. 接口 Document

[Exposed=Window]
interface Document : Node {
  constructor();

  [SameObject] readonly attribute DOMImplementation implementation;
  readonly attribute USVString URL;
  readonly attribute USVString documentURI;
  readonly attribute DOMString compatMode;
  readonly attribute DOMString characterSet;
  readonly attribute DOMString charset; // legacy alias of .characterSet
  readonly attribute DOMString inputEncoding; // legacy alias of .characterSet
  readonly attribute DOMString contentType;

  readonly attribute DocumentType? doctype;
  readonly attribute Element? documentElement;
  HTMLCollection getElementsByTagName(DOMString qualifiedName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);

  [CEReactions, NewObject] Element createElement(DOMString localName, optional (DOMString or ElementCreationOptions) options = {});
  [CEReactions, NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName, optional (DOMString or ElementCreationOptions) options = {});
  [NewObject] DocumentFragment createDocumentFragment();
  [NewObject] Text createTextNode(DOMString data);
  [NewObject] CDATASection createCDATASection(DOMString data);
  [NewObject] Comment createComment(DOMString data);
  [NewObject] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);

  [CEReactions, NewObject] Node importNode(Node node, optional boolean deep = false);
  [CEReactions] Node adoptNode(Node node);

  [NewObject] Attr createAttribute(DOMString localName);
  [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString qualifiedName);

  [NewObject] Event createEvent(DOMString interface); // legacy

  [NewObject] Range createRange();

  // NodeFilter.SHOW_ALL = 0xFFFFFFFF
  [NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
  [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
};

[Exposed=Window]
interface XMLDocument : Document {};

dictionary ElementCreationOptions {
  DOMString is;
};

Document 节点简称为文档

文档节点文档是它自己。

每个文档都有一个关联的编码(一个编码)、内容类型(一个字符串)、URL(一个URL)、来源(一个来源)、类型("xml"或"html")、模式("no-quirks"、"quirks"或"limited-quirks")和允许声明性影子根(一个布尔值)。[编码][URL][HTML]

除非另有说明,否则文档编码utf-8 编码内容类型是"application/xml",URL是"about:blank",来源不透明来源类型是"xml",模式是"no-quirks",并且允许声明性影子根为假。

文档被称为XML文档,如果其类型是"xml";否则称为HTML文档。文档是HTML文档还是XML文档会影响某些API的行为。

文档被称为无怪癖模式,如果其模式是"no-quirks",怪癖模式,如果其模式是"quirks",以及有限怪癖模式,如果其模式是"limited-quirks"。

模式只有在以下情况下才会从默认值更改:由文档HTML解析器根据DOCTYPE字符串的存在、缺失或值创建,或由新浏览上下文(初始"about:blank")创建时。[HTML]

无怪癖模式最初被称为“标准模式”,有限怪癖模式曾被称为“几乎标准模式”。它们被重命名是因为它们的细节现在由标准定义。(并且因为Ian Hickson以这些名字是荒谬的为理由否决了它们的原始名字。)

文档获取父级算法在给定一个事件的情况下,如果事件类型属性值是"load"或文档没有浏览上下文,则返回null;否则返回文档的相关全局对象


document . doctype
返回 doctype,如果没有则返回 null。
document . documentElement
返回 document element
collection = document . getElementsByTagName(qualifiedName)

如果 qualifiedName 是 "*",则返回一个包含所有 后代 元素HTMLCollection

否则,返回一个包含所有 后代 元素HTMLCollection,其 限定名qualifiedName。(在 HTML 命名空间中的 HTML 文档中,对 元素 进行不区分大小写的匹配。)

collection = document . getElementsByTagNameNS(namespace, localName)

如果 namespacelocalName 都是 "*",则返回一个包含所有 后代 元素HTMLCollection

如果只有 namespace 是 "*",则返回一个包含所有 后代 元素HTMLCollection,其 本地名localName

如果只有 localName 是 "*",则返回一个包含所有 后代 元素HTMLCollection,其 命名空间namespace

否则,返回一个包含所有 后代 元素HTMLCollection,其 命名空间namespace,且 本地名localName

collection = document . getElementsByClassName(classNames)
collection = element . getElementsByClassName(classNames)

返回在调用该方法的对象(一个 文档 或一个 元素)中具有所有由 classNames 指定的类的 元素HTMLCollectionclassNames 参数被解释为以空格分隔的类列表。

doctype 的 getter 步骤是返回 this 的一个 doctype 子节点;否则返回 null。

documentElement 的 getter 步骤是返回 thisdocument element

getElementsByTagName(qualifiedName) 方法的步骤是返回 具有限定名 qualifiedName 的元素列表,用于 this

因此,在 HTML 文档中,document.getElementsByTagName("FOO") 将匹配不在 HTML 命名空间中的 <FOO> 元素,以及在 HTML 命名空间中的 <foo> 元素,但不会匹配在 HTML 命名空间中的 <FOO> 元素。

getElementsByTagNameNS(namespace, localName) 方法的步骤是返回 具有命名空间 namespace 和本地名 localName 的元素列表,用于 this

getElementsByClassName(classNames) 方法的步骤是返回 具有类名 classNames 的元素列表,用于 this

给出以下的XHTML片段:
<div id="example">
  <p id="p1" class="aaa bbb"/>
  <p id="p2" class="aaa ccc"/>
  <p id="p3" class="bbb ccc"/>
</div>

调用document.getElementById("example").getElementsByClassName("aaa")将返回一个包含两个段落p1p2HTMLCollection

调用getElementsByClassName("ccc bbb")将只返回一个节点,即p3。调用document.getElementById("example").getElementsByClassName("bbb ccc ")将返回相同的内容。

调用getElementsByClassName("aaa,bbb")将不会返回任何节点;上面的元素中没有一个属于aaa,bbb类。


element = document . createElement(localName [, options])

返回一个localName本地名称元素(如果documentHTML文档,则localName将小写)。元素的命名空间documentHTML文档document内容类型为"application/xhtml+xml"时为HTML命名空间;否则为null。

如果localName不匹配名称的生成,则会抛出一个"InvalidCharacterError"DOMException

提供时,可以使用optionsis来创建定制内建元素

element = document . createElementNS(namespace, qualifiedName [, options])

返回一个具有namespace元素。它的命名空间前缀将是qualifiedName中U+003A (:)之前的所有内容,否则为null。它的本地名称将是qualifiedName中U+003A (:)之后的所有内容,或者是qualifiedName

如果qualifiedName不匹配QName的生成,则会抛出一个"InvalidCharacterError"DOMException

如果以下条件之一为真,则会抛出一个"NamespaceError"DOMException

提供时,可以使用optionsis来创建定制内建元素

documentFragment = document . createDocumentFragment()
返回一个DocumentFragment节点
text = document . createTextNode(data)
返回一个Text节点,其数据data
text = document . createCDATASection(data)
返回一个CDATASection节点,其数据data
comment = document . createComment(data)
返回一个Comment节点,其数据data
processingInstruction = document . createProcessingInstruction(target, data)
返回一个ProcessingInstruction节点,其目标target数据data。如果target不匹配名称的生成,则会抛出一个"InvalidCharacterError"DOMException。如果data包含"?>",则会抛出一个"InvalidCharacterError"DOMException

元素接口对于任何名称命名空间都是Element,除非另有说明。

例如,HTML标准将定义,对于htmlHTML命名空间,使用HTMLHtmlElement接口。[HTML]

createElement(localName, options)方法步骤如下:

  1. 如果localName不匹配名称的生成,则抛出一个"InvalidCharacterError"DOMException

  2. 如果this是一个HTML文档,则将localName设置为localName的小写形式。

  3. is设置为null。

  4. 如果options是一个字典,并且options["is"]存在,则将is设置为它。

  5. 如果this是一个HTML文档this内容类型为"application/xhtml+xml",则将namespace设置为HTML命名空间;否则为null。

  6. 返回给定thislocalNamenamespace、null、is和设置了同步自定义元素标志的创建元素的结果。

内部createElementNS步骤,给定documentnamespacequalifiedNameoptions,如下:

  1. namespaceprefixlocalName成为将namespacequalifiedName传递给验证和提取的结果。

  2. is设置为null。

  3. 如果options是一个字典,并且options["is"]存在,则将is设置为它。

  4. 返回给定documentlocalNamenamespaceprefixis和设置了同步自定义元素标志的创建元素的结果。

createElementNS(namespace, qualifiedName, options)方法步骤是返回给定thisnamespacequalifiedNameoptions运行内部createElementNS步骤的结果。

createElement()createElementNS()options参数允许为字符串以保持Web兼容性。

createDocumentFragment()方法步骤是返回一个新的DocumentFragment节点,其节点文档this

createTextNode(data)方法步骤是返回一个新的Text节点,其数据data,其节点文档this

不会检查data是否由符合Char生成规则的字符组成。

createCDATASection(data)方法步骤如下:

  1. 如果this是一个HTML文档,则抛出一个"NotSupportedError"DOMException

  2. 如果data包含字符串"]]>",则抛出一个"InvalidCharacterError"DOMException

  3. 返回一个新的CDATASection节点,其数据设置为data节点文档设置为this

createComment(data)方法步骤是返回一个新的Comment节点,其数据data,其节点文档this

不会检查data是否由符合Char生成规则的字符组成,或是否包含两个相邻的连字符或以连字符结尾。

createProcessingInstruction(target, data)方法步骤如下:

  1. 如果target不匹配Name的生成规则,则抛出一个"InvalidCharacterError"DOMException
  2. 如果data包含字符串"?>",则抛出一个"InvalidCharacterError"DOMException
  3. 返回一个新的ProcessingInstruction节点,其目标设置为target数据设置为data节点文档设置为this

不会检查target是否包含"xml"或":",或data是否由符合Char生成规则的字符组成。


clone = document . importNode(node [, deep = false])

返回node的副本。如果deep为true,则副本也包括node后代

如果node文档影子根,则抛出一个"NotSupportedError"DOMException

node = document . adoptNode(node)

node从另一个文档中移出并返回它。

如果node是一个文档,则抛出一个"NotSupportedError"DOMException;或者,如果node是一个影子根,则抛出一个"HierarchyRequestError"DOMException

importNode(node, deep)方法步骤如下:

  1. 如果node文档影子根,则抛出一个"NotSupportedError"DOMException

  2. 返回node副本this副本子项标志已设置(如果deep为true)。

规范可能会为所有或部分节点定义采用步骤。该算法将nodeoldDocument作为输入,如采用算法中所示。

要将某个node采用document中,执行以下步骤:

  1. oldDocument设为node节点文档

  2. 如果node父节点不为null,则移除node

  3. 如果document不是oldDocument,则:

    1. 对于node的每个包括影子在内的包容性后代

      1. 包括影子在内的包容性后代节点文档设置为document

      2. 如果包括影子在内的包容性后代是一个元素,则将包括影子在内的包容性后代的每个属性节点文档设置为document

    2. 对于node的每个包括影子在内的包容性后代,如果它是自定义元素,则入列一个自定义元素回调反应,其中包括包括影子在内的包容性后代、回调名称"adoptedCallback",以及包含oldDocumentdocument的参数列表。

    3. 对于node的每个包括影子在内的包容性后代,按包括影子在内的树顺序运行采用步骤,输入参数为包括影子在内的包容性后代oldDocument

adoptNode(node)方法步骤如下:

  1. 如果node是一个文档,则抛出一个"NotSupportedError"DOMException

  2. 如果node是一个影子根,则抛出一个"HierarchyRequestError"DOMException

  3. 如果node是一个DocumentFragment节点,其容器不为null,则返回。

  4. node采用到this

  5. 返回node


createAttribute(localName)方法步骤如下:

  1. 如果localName不匹配Name在XML中的生成规则,则抛出一个"InvalidCharacterError"DOMException

  2. 如果this是一个HTML文档,则将localName设置为ASCII小写形式

  3. 返回一个新的属性,其本地名称localName,其节点文档this

createAttributeNS(namespace, qualifiedName)方法步骤如下:

  1. namespaceprefixlocalName设为将namespacequalifiedName传递给验证和提取的结果。

  2. 返回一个新的属性,其命名空间namespace命名空间前缀prefix本地名称localName节点文档this


createEvent(interface)方法步骤如下:

  1. constructor设为null。

  2. 如果interface是与下表第一列中的任何字符串的ASCII不区分大小写匹配,则将constructor设置为同一行第二列中的接口:

    字符串 接口 注释
    "beforeunloadevent" BeforeUnloadEvent [HTML]
    "compositionevent" CompositionEvent [UIEVENTS]
    "customevent" CustomEvent
    "devicemotionevent" DeviceMotionEvent [DEVICE-ORIENTATION]
    "deviceorientationevent" DeviceOrientationEvent
    "dragevent" DragEvent [HTML]
    "event" Event
    "events"
    "focusevent" FocusEvent [UIEVENTS]
    "hashchangeevent" HashChangeEvent [HTML]
    "htmlevents" Event
    "keyboardevent" KeyboardEvent [UIEVENTS]
    "messageevent" MessageEvent [HTML]
    "mouseevent" MouseEvent [UIEVENTS]
    "mouseevents"
    "storageevent" StorageEvent [HTML]
    "svgevents" Event
    "textevent" TextEvent [UIEVENTS]
    "touchevent" TouchEvent [TOUCH-EVENTS]
    "uievent" UIEvent [UIEVENTS]
    "uievents"
  3. 如果constructor为null,则抛出一个"NotSupportedError"DOMException

  4. 如果constructor指示的接口未在相关全局对象中暴露给this,则抛出一个"NotSupportedError"DOMException

    通常用户代理在某些配置中禁用对触摸事件的支持,在这种情况下,此条款将适用于TouchEvent接口。

  5. event成为创建事件的结果,输入为constructor

  6. 初始化eventtype属性为空字符串。

  7. 初始化eventtimeStamp属性为调用当前高分辨率时间的结果,输入为this相关全局对象

  8. 初始化eventisTrusted属性为false。

  9. 取消设置event初始化标志

  10. 返回event

Event构造器应该被使用。


createRange()方法步骤是返回一个新的活动范围,其this为起始点(this, 0),并返回起始点终点

Range()构造器可以被使用。


createNodeIterator(root, whatToShow, filter)方法步骤如下:

  1. iterator成为一个新的NodeIterator对象。

  2. iteratoriterator参考设置为root

  3. iterator指针在参考之前设置为true。

  4. iteratorwhatToShow设置为whatToShow

  5. iterator过滤器设置为filter

  6. 返回iterator

createTreeWalker(root, whatToShow, filter)方法步骤如下:

  1. walker成为一个新的TreeWalker对象。

  2. walkerwalker当前节点设置为root

  3. walkerwhatToShow设置为whatToShow

  4. walker过滤器 设置为filter

  5. 返回walker

4.5.1.接口 DOMImplementation

用户代理在创建文档时,必须创建一个DOMImplementation对象,并将其与该文档关联。

[Exposed=Window]
interface DOMImplementation {
  [NewObject] DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
  [NewObject] XMLDocument createDocument(DOMString? namespace, [LegacyNullToEmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
  [NewObject] Document createHTMLDocument(optional DOMString title);

  boolean hasFeature(); // useless; always returns true
};
doctype = document . implementation . createDocumentType(qualifiedName, publicId, systemId)
返回具有给定qualifiedNamepublicIdsystemIddoctype。如果qualifiedNameName生产不匹配,将抛出“InvalidCharacterErrorDOMException,如果它不匹配QName生产,将抛出“NamespaceErrorDOMException
doc = document . implementation . createDocument(namespace, qualifiedName [, doctype = null])
返回一个具有qualifiedName作为local name,并且其namespacenamespaceXMLDocument,并且如果给出了doctype,它将作为其doctype

当使用namespacequalifiedName调用时,此方法抛出与createElementNS()方法相同的异常。

doc = document . implementation . createHTMLDocument([title])
返回一个已经构建了基本document,包括一个title元素,除非省略了title参数。

createDocumentType(qualifiedName, publicId, systemId)方法步骤如下:

  1. 验证qualifiedName

  2. 返回一个新的doctype,其qualifiedName为其namepublicId为其public IDsystemId为其system ID,并且其node document设置为document

不会检查publicId代码点是否匹配PubidChar生产,或systemId是否同时包含'"'和"'"。

createDocument(namespace, qualifiedName, doctype)方法步骤如下:

  1. document成为一个新的XMLDocument

  2. element为null。

  3. 如果qualifiedName不是空字符串,则将element设置为运行内部createElementNS步骤的结果,给定documentnamespacequalifiedName和一个空字典。

  4. 如果doctype非空,则将doctype附加document

  5. 如果element非空,则将element附加document

  6. document来源this关联的document来源

  7. document内容类型namespace决定:

    HTML namespace
    application/xhtml+xml
    SVG namespace
    image/svg+xml
    任何其他命名空间
    application/xml
  8. 返回document

createHTMLDocument(title)方法步骤如下:

  1. doc成为一个新的document,该文档是一个HTML document

  2. doc内容类型设置为“text/html”。

  3. 附加一个新的doctype,其“html”作为其名称,并将其节点文档设置为doc,附加到doc

  4. 附加根据doc创建的元素的结果,html,并将HTML namespace附加到doc

  5. 附加根据doc创建的元素的结果,head,并将HTML namespace附加到之前创建的html元素。

  6. 如果给出了title

    1. 附加根据doc创建的元素的结果,title,并将HTML namespace附加到之前创建的head元素。

    2. 附加一个新的Text节点,其数据设置为title(可以是空字符串),并将其节点文档设置为doc,附加到之前创建的title元素。

  7. 附加根据doc创建的元素的结果,body,并将HTML namespace附加到之前创建的html元素。

  8. doc来源this关联的document来源

  9. 返回doc

hasFeature()方法步骤如下返回true。

hasFeature()最初会报告用户代理是否声称支持给定的DOM功能,但经验表明,它远不如简单地检查所需对象、属性或方法是否存在来得可靠或细致。因此,它不再被使用,但为了确保旧页面不停止工作,它继续存在(并且仅返回true)。

4.6. 接口DocumentType

[Exposed=Window]
interface DocumentType : Node {
  readonly attribute DOMString name;
  readonly attribute DOMString publicId;
  readonly attribute DOMString systemId;
};

DocumentType 节点通常被称为 文档类型定义(doctypes)

文档类型定义(doctypes)具有 相关的名称(name)公有标识符(public ID)系统标识符(system ID)

创建文档类型定义(doctype)时,始终会提供其name。 除非在创建文档类型定义(doctype)时显式提供,否则其public IDsystem ID将为空字符串。

name获取器步骤是返回thisname

publicId获取器步骤是返回thispublic ID

systemId获取器步骤是返回thissystem ID

4.7. 接口DocumentFragment

[Exposed=Window]
interface DocumentFragment : Node {
  constructor();
};

DocumentFragment 节点有一个关联的 宿主(host)(为null或在不同元素节点树中)。除非另有说明,否则为null。

对象A是对象B包含宿主的包容性祖先(host-including inclusive ancestor), 如果AB包容性祖先, 或者如果B有一个非空的宿主, 并且AB包含宿主的包容性祖先宿主

DocumentFragment 节点宿主概念 对于HTML的模板(template) 元素和影子根(shadow roots)非常有用,并且会影响预插入(pre-insert)替换(replace)算法。

tree = new DocumentFragment()
返回一个新的DocumentFragment 节点

new DocumentFragment() 构造函数步骤 是将this节点文档设置为当前全局对象关联Document

4.8. 接口ShadowRoot

[Exposed=Window]
interface ShadowRoot : DocumentFragment {
  readonly attribute ShadowRootMode mode;
  readonly attribute boolean delegatesFocus;
  readonly attribute SlotAssignmentMode slotAssignment;
  readonly attribute boolean clonable;
  readonly attribute boolean serializable;
  readonly attribute Element host;
  attribute EventHandler onslotchange;
};

enum ShadowRootMode { "open", "closed" };
enum SlotAssignmentMode { "manual", "named" };

ShadowRoot 节点通常被称为 影子根(shadow roots)

影子根(Shadow roots)有一个关联的模式(mode)(“open”或“closed”)。

影子根(Shadow roots)有一个关联的委派焦点(delegates focus)。它最初设置为false。

影子根(Shadow roots)有一个关联的可用于元素内部(available to element internals)。它最初设置为false。

影子根(Shadow roots)有一个关联的声明性(declarative)(一个布尔值)。它最初设置为false。

影子根(Shadow roots)的关联宿主(host)从不为null。

影子根(Shadow roots)有一个关联的槽分配(slot assignment)(“manual”或“named”)。

影子根(Shadow roots)有一个关联的可克隆性(clonable)(一个布尔值)。它最初设置为false。

影子根(Shadow roots)有一个关联的可序列化性(serializable)(一个布尔值)。它最初设置为false。

给定一个event影子根(shadow root)获取父级(get the parent)算法返回null,如果event组合标志(composed flag)未设置并且影子根event路径的第一个结构的调用目标;否则返回影子根宿主

mode获取器步骤是返回this模式

delegatesFocus获取器步骤是返回this委派焦点(delegates focus)

slotAssignment获取器步骤是返回this槽分配

clonable获取器步骤是返回this可克隆性

serializable获取器步骤是返回this可序列化性

host获取器步骤是返回this宿主

onslotchange属性是一个事件处理程序IDL属性,用于onslotchange 事件处理程序,其事件处理程序事件类型slotchange


影子包括树顺序(shadow-including tree order)中,是影子包括的先序,深度优先遍历(shadow-including preorder, depth-first traversal)节点树影子包括的先序,深度优先遍历(Shadow-including preorder, depth-first traversal)tree的先序,深度优先遍历,在tree中遇到的每个影子宿主(shadow host)影子包括的先序,深度优先遍历元素影子根节点树,就在它被遇到之后。

shadow-including root 是对象的 roothostshadow-including root,如果对象的 root 是一个 shadow root;否则为它的 root

对象A是对象B影子包括的后代(shadow-including descendant),如果AB后代,或者A影子根,并且A宿主影子包括的包容性后代(shadow-including inclusive descendant)B

影子包括的包容性后代(shadow-including inclusive descendant)是一个对象或其影子包括的后代之一。

对象A是对象B影子包括的祖先(shadow-including ancestor),当且仅当BA影子包括的后代

影子包括的包容性祖先(shadow-including inclusive ancestor)是一个对象或其影子包括的祖先之一。

节点A节点B中是闭合影子隐藏的(closed-shadow-hidden),如果以下所有条件都为真:

为了重新定位(retarget)对象A相对于对象B,重复这些步骤直到返回一个对象:

  1. 如果以下情况之一为真

    那么返回A

  2. A设置为A宿主

重新定位(retargeting)算法由事件调度以及其他规范(如Fullscreen)使用。[FULLSCREEN]

4.9.接口Element

[Exposed=Window]
interface Element : Node {
  readonly attribute DOMString? namespaceURI;
  readonly attribute DOMString? prefix;
  readonly attribute DOMString localName;
  readonly attribute DOMString tagName;

  [CEReactions] attribute DOMString id;
  [CEReactions] attribute DOMString className;
  [SameObject, PutForwards=value] readonly attribute DOMTokenList classList;
  [CEReactions, Unscopable] attribute DOMString slot;

  boolean hasAttributes();
  [SameObject] readonly attribute NamedNodeMap attributes;
  sequence<DOMString> getAttributeNames();
  DOMString? getAttribute(DOMString qualifiedName);
  DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
  [CEReactions] undefined setAttribute(DOMString qualifiedName, DOMString value);
  [CEReactions] undefined setAttributeNS(DOMString? namespace, DOMString qualifiedName, DOMString value);
  [CEReactions] undefined removeAttribute(DOMString qualifiedName);
  [CEReactions] undefined removeAttributeNS(DOMString? namespace, DOMString localName);
  [CEReactions] boolean toggleAttribute(DOMString qualifiedName, optional boolean force);
  boolean hasAttribute(DOMString qualifiedName);
  boolean hasAttributeNS(DOMString? namespace, DOMString localName);

  Attr? getAttributeNode(DOMString qualifiedName);
  Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName);
  [CEReactions] Attr? setAttributeNode(Attr attr);
  [CEReactions] Attr? setAttributeNodeNS(Attr attr);
  [CEReactions] Attr removeAttributeNode(Attr attr);

  ShadowRoot attachShadow(ShadowRootInit init);
  readonly attribute ShadowRoot? shadowRoot;

  Element? closest(DOMString selectors);
  boolean matches(DOMString selectors);
  boolean webkitMatchesSelector(DOMString selectors); // legacy alias of .matches

  HTMLCollection getElementsByTagName(DOMString qualifiedName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);

  [CEReactions] Element? insertAdjacentElement(DOMString where, Element element); // legacy
  undefined insertAdjacentText(DOMString where, DOMString data); // legacy
};

dictionary ShadowRootInit {
  required ShadowRootMode mode;
  boolean delegatesFocus = false;
  SlotAssignmentMode slotAssignment = "named";
  boolean clonable = false;
  boolean serializable = false;
};

Element 节点通常被称为 元素(elements)

元素(Elements)有一个关联的命名空间(namespace)命名空间前缀(namespace prefix)本地名称(local name)自定义元素状态(custom element state)自定义元素定义(custom element definition)is。当创建元素时,所有这些值都会被初始化。

元素的自定义元素状态是“undefined”、“failed”、“uncustomized”、“precustomized”或“custom”之一。元素自定义元素状态为“uncustomized”或“custom”时,被称为已定义(defined)元素自定义元素状态为“custom”时,被称为自定义(custom)

元素是否被定义用于确定:defined伪类的行为。元素是否被自定义用于确定变动算法(mutation algorithms)的行为。“failed”和“precustomized”状态用于确保如果自定义元素构造函数(custom element constructor)第一次执行失败,它不会在元素升级(upgrade)时再次执行。

以下代码展示了处于这四种状态中的元素:

<!DOCTYPE html>
<script>
  window.customElements.define("sw-rey", class extends HTMLElement {})
  window.customElements.define("sw-finn", class extends HTMLElement {}, { extends: "p" })
  window.customElements.define("sw-kylo", class extends HTMLElement {
    constructor() {
      // super() intentionally omitted for this example
    }
  })
</script>

<!-- "undefined" (not defined, not custom) -->
<sw-han></sw-han>
<p is="sw-luke"></p>
<p is="asdf"></p>

<!-- "failed" (not defined, not custom) -->
<sw-kylo></sw-kylo>

<!-- "uncustomized" (defined, not custom) -->
<p></p>
<asdf></asdf>

<!-- "custom" (defined, custom) -->
<sw-rey></sw-rey>
<p is="sw-finn"></p>

元素 也有一个关联的 shadow root(为 null 或一个 shadow root)。除非另有说明,否则它为 null。如果一个 元素shadow root 不为 null,那么该元素就是一个 shadow host

元素的限定名称(qualified name)是其本地名称,如果其命名空间前缀为null;否则为其命名空间前缀,后跟“:”,再后跟其本地名称

元素的HTML大写限定名称(HTML-uppercased qualified name)的返回值通过以下步骤获得:

  1. qualifiedName成为this限定名称

  2. 如果this位于HTML命名空间中,并且其节点文档是一个HTML文档,则将qualifiedName设置为qualifiedNameASCII大写形式。

  3. 返回qualifiedName

用户代理可以通过将限定名称(qualified name)HTML大写限定名称(HTML-uppercased qualified name)存储在内部槽中来进行优化。

为了创建一个元素(create an element),给定documentlocalNamenamespace和可选的prefixissynchronous custom elements flag,执行以下步骤:

  1. 如果未给定prefix,则将prefix设为null。

  2. 如果未给定is,则将is设为null。

  3. result设为null。

  4. definition设为通过查找自定义元素定义给定documentnamespacelocalNameis的结果。

  5. 如果definition非null,并且definition名称不等于其本地名称(即definition表示一个定制内置元素(customized built-in element)),则:

    1. interface成为localNameHTML命名空间元素接口

    2. result设置为一个新的元素,该元素实现了interface,没有属性,命名空间设为HTML命名空间命名空间前缀设为prefix本地名称设为localName自定义元素状态设为“undefined”,自定义元素定义设为null,is设为is节点文档设为document

    3. 如果设置了synchronous custom elements flag,则在捕获任何异常的同时执行此步骤:

      1. 升级 result 使用 definition

      如果此步骤抛出异常,则:

      1. 报告异常

      2. result自定义元素状态设置为“failed”。

    4. 否则,排队一个自定义元素升级反应,给定resultdefinition

  6. 否则,如果definition非null,则:

    1. 如果设置了synchronous custom elements flag,则在捕获任何异常的同时执行以下步骤:

      1. Cdefinition构造函数

      2. result设为构造C的结果,没有参数。

      3. 断言:result自定义元素状态自定义元素定义已初始化。

      4. 断言:result命名空间HTML命名空间

        IDL 强制规定result是一个HTMLElement对象,所有这些对象都使用HTML命名空间

      5. 如果result属性列表不为空,则抛出NotSupportedErrorDOMException

      6. 如果result子节点,则抛出NotSupportedErrorDOMException

      7. 如果result父节点非空,则抛出NotSupportedErrorDOMException

      8. 如果result节点文档不是document,则抛出NotSupportedErrorDOMException

      9. 如果result本地名称不等于localName,则抛出NotSupportedErrorDOMException

      10. result命名空间前缀设置为prefix

      11. resultis设置为null。

      如果这些步骤中的任何一步抛出异常,则:

      1. 报告异常

      2. result设为一个新的元素,该元素实现了HTMLUnknownElement接口,没有属性,命名空间设为HTML命名空间命名空间前缀设为prefix本地名称设为localName自定义元素状态设为“failed”,自定义元素定义设为null,is设为null,节点文档设为document

    2. 否则:

      1. result设为一个新的元素,该元素实现了HTMLElement接口,没有属性,命名空间设为HTML命名空间命名空间前缀设为prefix本地名称设为localName自定义元素状态设为“undefined”,自定义元素定义设为null,is设为null,节点文档设为document

      2. 排队一个自定义元素升级反应,给定resultdefinition

  7. 否则:

    1. interface成为localNamenamespace元素接口

    2. result设置为一个新的元素,该元素实现了interface,没有属性,命名空间设为namespace命名空间前缀设为prefix本地名称设为localName自定义元素状态设为“uncustomized”,自定义元素定义设为null,is设为is节点文档设为document

    3. 如果namespaceHTML命名空间,并且localName是一个有效的自定义元素名称is非空,则将result自定义元素状态设置为“undefined”。

  8. 返回result

元素也有一个属性列表,它是通过NamedNodeMap公开的一个列表。除非在创建元素时明确指定,否则其属性列表为空

如果元素的元素具有属性A,则其属性列表包含A

本规范和其他规范可能为元素定义属性更改步骤。该算法传递elementlocalNameoldValuevaluenamespace

处理属性更改,对于具有elementoldValuenewValue的属性attribute,执行以下步骤:

  1. 排队一个突变记录,内容为“attributes”,适用于element,包含attribute本地名称attribute命名空间oldValue、“« »”和null。

  2. 如果element自定义的,则排队一个自定义元素回调反应,适用于element,回调名称为“attributeChangedCallback”,并包含一个参数列表,其中包含attribute本地名称oldValuenewValueattribute命名空间

  3. 运行属性更改步骤,给定elementattribute本地名称oldValuenewValueattribute命名空间

更改属性attributevalue,执行以下步骤:

  1. oldValue设为attribute

  2. attribute设为value

  3. 处理属性更改,适用于attribute,包括attribute元素oldValuevalue

附加属性attribute到元素element,执行以下步骤:

  1. attribute附加到element属性列表

  2. attribute元素设为element

  3. 处理属性更改,适用于attribute,包括element、null和attribute

移除属性attribute,执行以下步骤:

  1. element设为attribute元素

  2. element属性列表中移除attribute
  3. attribute元素设为null。

  4. 处理属性更改,适用于attribute,包括elementattribute和null。

替换属性oldAttr为属性newAttr,执行以下步骤:

  1. 替换oldAttrnewAttr,在oldAttr元素属性列表中。

  2. newAttr元素设为oldAttr元素

  3. oldAttr元素设为null。

  4. 处理属性更改,适用于oldAttr,包括newAttr元素oldAttrnewAttr


按名称获取属性,给定一个字符串qualifiedName和一个元素element

  1. 如果element位于HTML命名空间中,且其节点文档是一个HTML文档,则将qualifiedName转换为ASCII小写

  2. 返回element属性列表中第一个qualifiedName匹配的限定名称属性;否则返回null。

按命名空间和本地名称获取属性,给定null或一个字符串namespace、一个字符串localName和一个元素element

  1. 如果namespace为空字符串,则将其设置为null。

  2. 返回element属性列表中,namespacelocalName匹配的命名空间本地名称属性;如果没有,则返回null。

获取属性值,给定一个元素element、一个字符串localName,以及一个可选的null或字符串namespace(默认值为null):

  1. attr是按命名空间和本地名称获取属性的结果,给定namespacelocalNameelement

  2. 如果attr为null,则返回空字符串。

  3. 返回attr

设置属性,给定一个属性attr和一个元素element

  1. 如果attr元素既不为null也不为element,则抛出一个“InUseAttributeErrorDOMException

  2. oldAttr是按命名空间和本地名称获取属性的结果,给定attr命名空间attr本地名称element

  3. 如果oldAttrattr,则返回attr

  4. 如果oldAttr不为null,则用attr替换oldAttr

  5. 否则,将attr附加到element

  6. 返回oldAttr

设置属性值,给定一个元素element、一个字符串localName、一个字符串value,一个可选的null或字符串prefix(默认值为null),以及一个可选的null或字符串namespace(默认值为null):

  1. attribute是按命名空间和本地名称获取属性的结果,给定namespacelocalNameelement

  2. 如果attribute为null,则创建一个属性,其命名空间namespace命名空间前缀prefix本地名称localNamevalue节点文档element节点文档,然后将该属性附加到element,然后返回。

  3. 更改attributevalue

按名称移除属性,给定一个字符串qualifiedName和一个元素element

  1. attr是按名称获取属性的结果,给定qualifiedNameelement

  2. 如果attr不为null,则移除attr

  3. 返回attr

按命名空间和本地名称移除属性,给定null或一个字符串namespace、一个字符串localName和一个元素element

  1. attr是按命名空间和本地名称获取属性的结果,给定namespacelocalNameelement

  2. 如果attr不为null,则移除attr

  3. 返回attr


一个 元素 可以有一个关联的 唯一标识符(ID)

历史上,元素 可以通过使用 HTML 的 id 属性 和 DTD 拥有多个标识符。该规范将 ID 作为 DOM 的概念,并允许每个 元素 只有一个由 id 属性 给出的标识符。

使用这些 属性更改步骤 来更新一个 元素ID

  1. 如果 localNameidnamespace 为 null,且 value 为 null 或为空字符串,则取消 elementID

  2. 否则,如果 localNameidnamespace 为 null,则将 elementID 设置为 value

虽然本规范定义了任何 元素classidslot 属性 的要求,但并未说明使用它们是否符合规范。


一个 节点 类型为 Element父节点 被称为它的 父元素。如果 节点父节点 是不同类型,它的 父元素 为 null。


namespace = element . namespaceURI
返回 命名空间
prefix = element . prefix
返回 命名空间前缀
localName = element . localName
返回 本地名称
qualifiedName = element . tagName
返回 HTML大写合格名称

namespaceURI 的 getter 步骤是返回 this命名空间

prefix 的 getter 步骤是返回 this命名空间前缀

localName 的 getter 步骤是返回 this本地名称

tagName 的 getter 步骤是返回 thisHTML大写合格名称


element . id [ = value ]

返回 elementid 内容属性的值。可以设置以更改它。

element . className [ = value ]

返回 elementclass 内容属性的值。可以设置以更改它。

element . classList

允许通过 DOMTokenList 对象以一组以空格分隔的标记来操作 elementclass 内容属性。

element . slot [ = value ]

返回 elementslot 内容属性的值。可以设置以更改它。

定义为 反映字符串 name 的 IDL 属性,必须有这些 getter 和 setter 步骤:

getter 步骤

返回运行 获取属性值 的结果,给定 thisname

setter 步骤

设置属性值,给定 this,使用 name 和给定的值。

id 属性必须 反映 "id"。

className 属性必须 反映 "class"。

classList 的 getter 步骤是返回一个 DOMTokenList 对象,其关联的 元素this,且其关联的 属性本地名称class。这个特定 DOMTokenList 对象的 标记集 也被称为 元素

slot 属性必须 反映 "slot"。

idclassslot 实际上是超级全局属性,因为它们可以出现在任何元素上,无论该元素的命名空间如何。


element . hasAttributes()

如果 element 有属性则返回 true;否则返回 false。

element . getAttributeNames()

返回 element 的所有 限定名称。可能包含重复项。

element . getAttribute(qualifiedName)

返回 element 的第一个 属性,其 限定名称qualifiedName,如果没有这样的 属性,则返回 null。

element . getAttributeNS(namespace, localName)

返回 element属性,其 命名空间namespace,且 本地名称localName,如果没有这样的 属性,则返回 null。

element . setAttribute(qualifiedName, value)

设置 element 的第一个 属性,其 限定名称qualifiedName,并将其设置为 value

element . setAttributeNS(namespace, localName, value)

设置 element属性,其 命名空间namespace,且 本地名称localName,并将其设置为 value

element . removeAttribute(qualifiedName)

移除 element 的第一个 属性,其 限定名称qualifiedName

element . removeAttributeNS(namespace, localName)

移除 element属性,其 命名空间namespace,且 本地名称localName

element . toggleAttribute(qualifiedName [, force])

如果没有给定 force,则“切换” qualifiedName,如果存在则移除它,如果不存在则添加它。如果 force 为 true,则添加 qualifiedName。如果 force 为 false,则移除 qualifiedName

如果 qualifiedName 现在存在则返回 true;否则返回 false。

element . hasAttribute(qualifiedName)

如果 element 具有 属性,其 限定名称qualifiedName,则返回 true;否则返回 false。

element . hasAttributeNS(namespace, localName)

如果 element 具有 属性,其 命名空间namespace,且 本地名称localName,则返回 true;否则返回 false。

hasAttributes() 方法的步骤是,如果 this属性列表 为空,则返回 false;否则返回 true。

attributes 的 getter 步骤是返回关联的 NamedNodeMap

getAttributeNames() 方法的步骤是按顺序返回 限定名称,如果存在,属性this属性列表 中;否则返回一个新的 列表

这些不能保证是唯一的。

getAttribute(qualifiedName) 方法的步骤是:

  1. attr 成为通过 获取属性 的结果,给定 qualifiedNamethis

  2. 如果 attr 为 null,则返回 null。

  3. 返回 attr

getAttributeNS(namespace, localName) 方法的步骤是:

  1. attr 成为通过 获取属性 的结果,给定 namespacelocalNamethis

  2. 如果 attr 为 null,则返回 null。

  3. 返回 attr

setAttribute(qualifiedName, value) 方法的步骤是:

  1. 如果 qualifiedName 与 XML 中的 Name 生产不匹配,则 抛出 一个 "InvalidCharacterError" DOMException

  2. 如果 thisHTML 命名空间 中,并且其 节点文档HTML 文档,则将 qualifiedName 设置为 qualifiedNameASCII 小写字母

  3. attribute 成为 this属性列表 中第一个 属性,其 限定名称qualifiedName,否则为 null。

  4. 如果 attribute 为 null,创建一个 属性,其 本地名称qualifiedNamevalue节点文档this节点文档,然后 将此属性添加this,然后返回。

  5. 更改 attributevalue

setAttributeNS(namespace, qualifiedName, value) 方法的步骤是:

  1. namespaceprefixlocalName 作为传递 namespacequalifiedName 的结果传递给 验证和提取

  2. 使用 localNamevalue 以及 prefixnamespace 设置属性值

removeAttribute(qualifiedName) 方法的步骤是给定 qualifiedNamethis 移除属性,然后返回 undefined。

removeAttributeNS(namespace, localName) 方法的步骤是给定 namespacelocalNamethis 移除属性,然后返回 undefined。

hasAttribute(qualifiedName) 方法的步骤是:

  1. 如果 thisHTML 命名空间 中,并且其 节点文档HTML 文档,则将 qualifiedName 设置为 qualifiedNameASCII 小写字母

  2. 如果 this 具有一个 属性,其 限定名称qualifiedName,则返回 true;否则返回 false。

toggleAttribute(qualifiedName, force) 方法的步骤是:

  1. 如果 qualifiedName 与 XML 中的 Name 生产不匹配,则 抛出 一个 "InvalidCharacterError" DOMException

  2. 如果 thisHTML 命名空间 中,并且其 节点文档HTML 文档,则将 qualifiedName 设置为 qualifiedNameASCII 小写字母

  3. attribute 成为 this属性列表 中第一个 属性,其 限定名称qualifiedName,否则为 null。

  4. 如果 attribute 为 null,则:

    1. 如果未给定 force 或为 true,创建一个 属性,其 本地名称qualifiedName 为空字符串,节点文档this节点文档,然后 将此属性添加this,然后返回 true。

    2. 返回 false。

  5. 否则,如果未给定 force 或为 false,给定 qualifiedNamethis 移除属性,然后返回 false。

  6. 返回 true。

hasAttributeNS(namespace, localName) 方法的步骤是:

  1. 如果 namespace 为空字符串,则将其设置为 null。

  2. 如果 this 具有一个 属性,其 命名空间namespace,且 本地名称localName,则返回 true;否则返回 false。

getAttributeNode(qualifiedName) 方法的步骤是返回给定 qualifiedNamethis获取属性 的结果。

getAttributeNodeNS(namespace, localName) 方法的步骤是返回给定 namespacelocalNamethis获取属性 的结果。

setAttributeNode(attr)setAttributeNodeNS(attr) 方法的步骤是返回给定 attrthis设置属性 的结果。

removeAttributeNode(attr) 方法的步骤如下:

  1. 如果 this属性列表包含 attr,则 抛出 一个 "NotFoundError" DOMException

  2. 移除 attr

  3. 返回 attr


var shadow = element . attachShadow(init)

element 创建一个 shadow root 并返回它。

var shadow = element . shadowRoot

返回 elementshadow root,如果有,并且如果 shadow rootmode 是 "open",否则返回 null。

有效的 shadow 宿主名称 是:

attachShadow(init) 方法的步骤是:

  1. 运行 附加一个 shadow root,使用 thisinit["mode"], init["clonable"], init["serializable"], init["delegatesFocus"], 和 init["slotAssignment"]。

  2. 返回 thisshadow root

附加一个 shadow root,给定一个 元素 element,一个字符串 mode,一个布尔值 clonable,一个布尔值 serializable,一个布尔值 delegatesFocus,和一个字符串 slotAssignment

  1. 如果 element命名空间 不是 HTML 命名空间,则 抛出一个 "NotSupportedError" DOMException

  2. 如果 element本地名称 不是一个 有效的 shadow 宿主名称,则 抛出一个 "NotSupportedError" DOMException

  3. 如果 element本地名称 是一个 有效的自定义元素名称,或者 elementis 不为空,则:

    1. definition 成为给定 element节点文档、其 命名空间、其 本地名称 和其 is查找自定义元素定义 的结果。

    2. 如果 definition 不为空并且 definition禁用 shadow 为真,则 抛出一个 "NotSupportedError" DOMException

  4. 如果 element 是一个 shadow 宿主,则:

    1. currentShadowRoot 成为 elementshadow root

    2. 如果以下任意一项为真:

      • currentShadowRoot声明式 为假;或者

      • currentShadowRoot模式 不为 mode

      抛出一个 "NotSupportedError" DOMException

    3. 否则:

      1. 移除 currentShadowRoot 的所有 子节点,按 树顺序

      2. currentShadowRoot声明式 设置为假。

      3. 返回。

  5. shadow 成为一个新的 shadow root,其 节点文档element节点文档宿主element模式mode

  6. shadowdelegates focus 设置为 delegatesFocus

  7. 如果 element自定义元素状态 是 "precustomized" 或 "custom",则将 shadow可用于元素内部 设置为真。

  8. shadowslot assignment 设置为 slotAssignment

  9. shadow声明式 设置为假。

  10. shadowclonable 设置为 clonable

  11. shadowserializable 设置为 serializable

  12. elementshadow root 设置为 shadow

shadowRoot getter 方法的步骤是:

  1. shadow 成为 thisshadow root

  2. 如果 shadow 为 null 或其 模式 为 "closed",则返回 null。

  3. 返回 shadow


element . closest(selectors)
返回第一个(从 element 开始)匹配 selectors包含祖先,否则返回 null。
element . matches(selectors)
如果匹配 selectors 时,element 返回 element,则返回 true;否则返回 false。

closest(selectors) 方法的步骤是:

  1. s 成为从 selectors 解析选择器 的结果。[SELECTORS4]

  2. 如果 s 解析失败,则 抛出一个 "SyntaxError" DOMException

  3. elements 成为 this包含祖先,这些祖先是 元素,按 树顺序 逆序排列。

  4. 对于 elements 中的每个 element,如果使用 selementscoping root 匹配选择器成功,则返回 element[SELECTORS4]

  5. 返回 null。

matches(selectors)webkitMatchesSelector(selectors) 方法的步骤是:

  1. s 成为从 selectors 解析选择器 的结果。[SELECTORS4]

  2. 如果 s 解析失败,则 抛出一个 "SyntaxError" DOMException

  3. 如果使用 sthisscoping root 匹配选择器的结果为成功,则返回 true;否则返回 false。[SELECTORS4]


getElementsByTagName(qualifiedName) 方法的步骤是返回 具有限定名称 qualifiedName 的元素列表,用于 this

getElementsByTagNameNS(namespace, localName) 方法的步骤是返回 具有命名空间 namespace 和本地名称 localName 的元素列表,用于 this

getElementsByClassName(classNames) 方法的步骤是返回 具有类名 classNames 的元素列表,用于 this


插入相邻元素,给定一个 元素 element、字符串 where 和一个 节点 node,执行与 where 的第一个 ASCII 不区分大小写 匹配相关的步骤:

"beforebegin"

如果 element父节点 为 null,则返回 null。

返回 预插入 nodeelement父节点,在 element 之前的结果。

"afterbegin"

返回 预插入 nodeelement 之前 element第一个子节点的结果。

"beforeend"

返回 预插入 nodeelement 之前 null 的结果。

"afterend"

如果 element父节点 为 null,则返回 null。

返回 预插入 nodeelement父节点element下一个兄弟节点之前的结果。

否则

抛出 "SyntaxError" DOMException

insertAdjacentElement(where, element) 方法的步骤是返回运行 插入相邻元素 的结果,给定 thiswhereelement

insertAdjacentText(where, data) 方法的步骤是:

  1. 创建一个新的 Text 节点,其 数据data,并且 节点文档this节点文档

  2. 运行 插入相邻元素,给定 thiswheretext

此方法不返回任何内容,因为它在我们有机会设计它之前就已存在。

4.9.1. 接口 NamedNodeMap

[Exposed=Window,
 LegacyUnenumerableNamedProperties]
interface NamedNodeMap {
  readonly attribute unsigned long length;
  getter Attr? item(unsigned long index);
  getter Attr? getNamedItem(DOMString qualifiedName);
  Attr? getNamedItemNS(DOMString? namespace, DOMString localName);
  [CEReactions] Attr? setNamedItem(Attr attr);
  [CEReactions] Attr? setNamedItemNS(Attr attr);
  [CEReactions] Attr removeNamedItem(DOMString qualifiedName);
  [CEReactions] Attr removeNamedItemNS(DOMString? namespace, DOMString localName);
};

一个 NamedNodeMap 有一个关联的 元素(一个 元素)。

一个 NamedNodeMap 对象的 属性列表 是它的 元素属性列表


一个 NamedNodeMap 对象的 支持的属性索引 是 零到它的 属性列表大小 减一范围内的数字, 除非 属性列表 为空, 在这种情况下没有 支持的属性索引

length 获取器步骤是返回 属性列表大小

item(index) 方法 步骤为:

  1. 如果 index 等于或大于 this属性列表大小,则返回 null。

  2. 否则,返回 this属性 列表[index]。

一个 NamedNodeMap 对象的 支持的属性名称 是运行 这些步骤返回的值:

  1. names 成为此 NamedNodeMap 对象的 属性列表