Copyright © 2012 W3C© (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
该规范介绍了允许开发者在文档里定义和使用新的DOM元素类型的方法
本节介绍此文档发布时的状态。其他文档可能取代此文档。在 W3C 技术报告索引 (http://www.w3.org/TR/) 可以找到此技术报告的当前W3C发布版本和最新修订版本列表。
此文档是由 Web应用工作组 发布的编辑草案。如果你想提交关于此文档的评论,请发送至 public-webapps@w3.org (订阅,存档)。 欢迎任何反馈。
发布为编辑草案并不意味着 W3C 会员的认可。这是一个文档草案,可能在任何时候更新、覆盖或被其他文档替代。不宜在在产品中引用此文档。
此文档由 W3C 专利政策 (2004-02-05) 操作的一个小组出品。 W3C 维护一个关联此小组产出成果的 专利声明的公开名单,该页面还包含了专利公开说明书。根据 W3C 专利政策第6条,拥有专利实际知识,且相信包含基本权利的人必须公开相关信息。
所有图表,示例,备注,以及明确标记为非规范的部分都是非规范的。其他内容都是规范的。
在本文档的规范部分中的关键字 "必须", "禁止", "要求", "会", "不会", "应该", "不应该", "推荐", "可以", 和 "可选" 在 RFC2119 的描述中有解释。为了方便阅读,这些词语不会以全部大写字母出现在本规范。
任何时刻,一个符合UA必须对状态或概念模型状态的反应做决定。这被称为算法。这些算法根据等价处理定义。等价处理 是强加给算法实现者的约束。对于相同的输入,要求UA实现和指定算法的输出必须保持完全一致。
文档依赖以下规范:
有两个动机,加剧了本规范的发展:
大部分花在寻找两个动机平衡的努力,由动机不是相互违背而且是互补的愿望驱使。例如,尽管该规范的范围目前仅限于由作者创建自定义的元素,它旨在缩短与一个更加宏伟目标的距离,这个目标是理顺所有的HTML,SVG和MathML元素到一个连贯的系统。
自定义元素是一个 平台对象其接口由开发者定义。自定元素的接口的接口原型对象被称为 自定义元素原型。
自定义元素类型 标识一个自定义元素接口 必须和NCName 产生方式相匹配的字符串,必须包含一个U+002D连字符号字符, 且不能包含任何ASCII大写字母. 自定义元素类型禁止是下面的任何一种:
annotation-xml
color-profile
font-face
font-face-src
font-face-uri
font-face-format
font-face-name
missing-glyph
元素定义描述了一个自定义元素,包括:
在创建时, 文档可以和一个注册表关联。注册表是元素定义的集合。
元素注册是一个添加元素定义到一个注册表的过程。 一个元素定义只能被注册到一个注册表.
如果一个文档 有一个与之关联的 注册 , 那么这个 文档 和在这个 注册表特定的 元素定义 , 自定义元素的接口 必须是 元素接口 ,分别为 自定义元素类型的 本地命名 和 命名空间值,和元素定义的命名空间。
如果一个文档 没有一个 注册表与它关联, 所有元素注册 的尝试就会失败。
确切建立注册,与文档关联, 元素注册在这个规范被进一步定义 。
一个 自定义元素 可以在它的生命周期贯穿这些改变:
各种回调函数被调用当一个自定义元素 贯穿这些变化。这些回调函数在内部以建-值对的集合存储,被称为生命周期回调函数。
把一个被称作 name 的回调函数从一个被称作property的对象属性转移到 生命周期回调,用户代理 必须 执行以下步骤:
为了方便调用回调函数, 相关的类似浏览上下文的每个单元 有一个处理堆栈, 最初是空的。堆栈的每一项是一个元素队列,最初也是空的。元素队列的每一项是一个 自定义元素。
每个 自定义元素有一个相关的回调队列和一个元素被创建成为 标志。标志最初设置为 false 以及 回调队列 最初是空的。在队列中的每项包含回调本身和零个或多个被用作回调参数的字符串值。
在一个 元素队列调用回调函数, 用户代理必须 执行这些步骤或类似:
任何时候,一个脚本调用一个方法,读取或设置属性由用户代理执行,下面的操作必须出现:
除了一个元素队列, 也有一个排队的元素队列。 自定义元素被保存在增加 自定义元素顺序的顺序中。
自定义元素顺序 是文档自定义元素顺序和 输入树顺序的总和, 其中 输入树顺序 被控制以使它的最低值总是比文档自定义元素顺序的最高可能值要大。
文档自定义元素顺序是一个数值,与每一个自定义元素相关。 这个值是 自定义元素的文档 保持一个递增的数值并分配到 自定义元素 作为它的 自定义元素顺序 每当发生以下情况的结果:
输入树的特定自定义元素 的输入树顺序
由被压入每个输入链路
用输入文档的内容来替换的输入树的树顺序决定。
最稳定的顺序 是紧接着前面的一个元素在第一个入口的 自定义元素顺序的值,在树顺序, 其 准备好的标志 尚未设定。 如果不存在这样的元素, 最高的稳定顺序在扁平的输入树里 是最高的自定义元素。
由于输入异步加载, 我们需要将一个有序的元素放入已经稳定的队列里(所有的输入已经加载),以及一直还在加载的部分里,因此实际排序顺序尚未确定。 例如,假设您有以下文件结构:
index.html:
<link rel="import" href="import.html">
...
<me-second></me-second>
...
import.html:
<me-first></me-first>
自定义元素在扁平输入树的顺序是 me-first
(1), me-second
(2)。 然而, 解析器很可能找到me-second
快于me-first
,因为后者需要加载 import.html
。当网络堆栈在执行时,最高的稳定顺序停留在最初的位置。当 import.html
已经准备好了, 顺序会跳到me-second
(2).
每一个 与浏览器上下文相关的单元有一个最初为空的存储元素队列, 被成为 基本元素队列.
作为microtask checkpoint的一部分, 用户代理 必须 处理基础元素队列与浏览器上下文相关的单元到 脚本浏览上下文。
为了阻止重写,当 处理基础元素队列时,每一个 与浏览器上下文相关的单元有一个处理基础元素队列 标志, 必须 初始化为false.
为了处理基本元素队列, 用户代理必须 执行以下步骤或 同等:
在属于脚本浏览上下文 与浏览器上下文相关的单元 , 当前元素队列是 处理堆栈 的顶部的元素队列,或是基本元素队列 如果 处理堆栈 为空。
要排队一个生命周期回调, 用户代理必须运行以下步骤或等同:下面的回调确认:
要在自定义元素上 设置自定义元素的原型, 用户代理 必须 执行以下步骤或 同等:
当一个 HTML Document 被加载 进一个 浏览上下文,一个新的 注册 必须 被创建且关联到这个document。
一个新 document 实例 必须 被关联到一个现有 注册 在这些例子里:
DOMImplementation
的 createDocument
方法被调用命名空间 设置为 HTML Namespace 或者当 createHTMLDocument
方法被调用, 使用与实例关联的document的注册在所有情况下, 新的 documents 不能 有一个 注册。
因为 元素注册 可在任何时间发生, 一个自定义元素在它的 定义 被 注册之前可能被创建。 这样的 自定义元素 实例被称为 unresolved elements。当一个unresolved element 被创建, 且 如果它的元素实例 没有被 HTML 或者 其他适用的规范定义。 unresolved element的元素实例 必须 是:
HTMLElement
, 如果 命名空间是HTML
命名空间;SVGElement
, 如果 命名空间 是 SVG
命名空间;或者每个 注册 有一个相关联的给出一对自定义元素类型 和 命名空间的所有unresolved elements 实例的表。这些数据结构被称为 升级的候选表 且初始化是空 。在表里的每项值是一个存储元素队列。
无论何时一个unresolved element被创建,必须 被添加到相应的 存储元素队列 在升级的候选表里。
注册 一个 元素定义是元素配准算法的职责, 必须 是等于 执行这些步骤:
定义构造算法创建一个 元素定义 , 必须 等同于 运行这些步骤:
None
, InvalidType
, InvalidName
, 或者 DuplicateDefinition
None
无效类型
且 停止。SVGElement
继承,设置NAMESPACE 为 SVG 命名空间重复定义
且 停止。无效命名
且 停止。元素升级算法 升级 unresolved elements,它的定义现在被 注册 且 必须 等同于 运行这些步骤:
文档
接口文档 接口的 注册元素
方法提供了一种
注册 和 返回它的 自定义元素构造函数的方法。
partial interface Document {
Function registerElement(DOMString type, optional ElementRegistrationOptions options);
};
dictionary ElementRegistrationOptions {
object? prototype = null;
DOMString? extends = null;
};
调用时, 注册元素
方法 必须 执行这些步骤:
Object.create
用HTMLElement
的
接口原型对象 作为唯一参数的结果。无效类型
,抛出 语法错误
且 停止。None
, 抛出 不支持错误
且 停止。元素注册选项
是一个允许使用函数对象和ES6类作为 document.register
方法的第二个参数的概念。
为了用原型去注册 一个自定义元素 ,其他 HTMLElement
或是SVGElement
, document.registerElement
的访问必须创建一个正确的从
HTMLElement
继承的原型对象。这里有一个简单的例子:
document.registerElement('x-foo', {
prototype: Object.create(HTMLParagraphElement.prototype, {
firstMember: {
get: function() { return "foo"; },
enumerable: true,
configurable: true
},
// specify more members for your prototype.
// ...
}),
extends: 'p'
});
注意:使用 扩展
选项去指定该元素被注册成为一个类型扩展 -- 就是说, 这个元素没有引入一个新标签 (像 自定义标签 元素那样), 而是扩展HTMLParagraphElement现有类型元素。 这里怎样实例化这种元素:
<p is="x-foo">Paragraph of amazement</p>
或者用JavaScript命令:
var foo = document.createElement('p', 'x-foo');
用SVGElement
原型的元素值得一提的是: 使用 自定义标签方法 的结果是在SVG忽略元素。 因此, 基于SVG的自定义元素可能几乎始终是 类型扩展名。
:unresolved
伪类 必须 匹配所有被创建的回调还没有被调用的 自定义元素。
:unresolved
伪类 可以用来减轻 没有样式内容的Flash (FOUC) 问题 用 自定义元素。
自定义元素类型 被给到一个自定义元素在它的实例的两种方式中的一种:
自定义元素 被实例化之后,改变它的属性 值不能影响该元素的自定义元素类型。
如果两种自定义元素类型在元素实例化的时候被提供, 自定义标签 必须 胜过 类型扩展。
所有 自定义元素 必须 可用 函数对象构建,被称为 自定义元素构建函数。该构造函数 必须 用自定义元素构造函数生成算法生成, 可以 等于 执行这些步骤:
文档
接口要允许同时创建 自定义标签 和 类型扩展式 自定义元素,
在createElement
或 createElementNS
方法有 重载一个 typeExtension
参数:
partial interface Document {
Element createElement(DOMString localName, DOMString typeExtension);
Element createElementNS(DOMString? namespace, DOMString qualifiedName, DOMString typeExtension);
};
替代在createElement
里的步骤3 和在 createElementNS
里的步骤9,即这些步骤确定 元素接口,两种方法 必须 执行以下步骤:
创建元素
)此外, createElement
和 createElementNS
方法 必须 执行下列步骤在结果返回
之前:
在树构造函数期间启用实例化 自定义元素 , 一个符合标准的 UA 必须 执行 排队 created 回调函数无论何时 创建 一个自定义元素。
一旦 ECMAScript标准版6被发布,这部分将纳入该规范的各个区域。 在此之前,这里是ECMAScript 6和自定义元素是如何整合的概述。
如果用户代理实现了@@create
方法, 本规范将会停止处理 ElementRegistrationOptions 选项
在 registerElement
作为一个词典的争议 ,相反把它看做是一个 自定义元素构造函数。
用户代理将会用一个新的@@create
方法创建一个新的元素对象改变这种争议,而不是用一个构造函数去创建。
由于registerElement
的第二个参数现在是一个构造函数, 该元素定义 应改为持有构造函数,而不是 自定义元素原型。
为了适应这种变化, 元素注册算法为下面的两步:
当 registerElement
的步骤执行时会改变:
FunctionAllocate
和 HTMLElement
作为functionPrototype 的结果,且结果是严格的trueHTMLElement
的接口原型对象 作为唯一参数的结果DefinePropertyOrThrow(
PROTOTYPE, "constructor", PropertyDescriptor{[[Value]]:
FUNCTION, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false})
DefinePropertyOrThrow(
FUNCTION, "prototype", PropertyDescriptor{[[Value]]:
PROTOTYPE, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false})
获取(
FUNCTION, "prototype")
的结果无效类型
, 抛出 一个 SyntaxError
且 停止。None
, 抛出 一个 NotSupportedError
且 停止。同样,自定义元素的构造函数生成算法将发生如下改变:
NotSupportedError
且 停止。DefinePropertyOrThrow(
FUNCTION, @@create, PropertyDescriptor{[[Value]]:
CREATE, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false})
为了帮助导航规范及其相互作用的各个部分,这里有一个表试图放进在同一个空间出发的所有算法执行。点击每个框去相应的算法或执行。
David Hyatt 开发了 XBL 1.0,Ian Hickson 参与了 XBL 2.0 的编写。这些文献在行为依附问题上提供了巨大而深刻的见解,并极大地影响了本说明书。
Alex Russell 和他的重要远见引发了新一波围绕行为依附课题的热潮和如何在网络上应用于实践。
Dominic Cooney 和 Roland Steiner 不知疲倦的仔细研究网络平台范围内的问题,为此文档打下了坚实的基础。
编辑还要感谢 Alex Komoroske,Angelina Fabbro,Anne van Kesteren,Boris Zbarsky,Brian Kardell,Daniel Buchner,Edward O'Connor,Eric Bidelman,Erik Arvidsson,Elliott Sprehn,Gabor Krizsanits,Hayato Ito,James Simonsen,Jonas Sicking,Ken Shirriff,Neel Goyal,Olli Pettay,Rafael Weinstein,Scott Miles,Steve Orvell,Tab Atkins,William Chan,和 William Chen,感谢他们对此说明书的评论和贡献。
这个列表太短了。还有很多工作要做。请通过评审和提交bugs来参与贡献 — 不要忘了要求编辑添加你的名字到此章节。