Warning:
This wiki has been archived and is now read-only.
HTML5/HTMLTemplates
本规范描述了一种方法,这种方法用来描述延迟的 HTML DOM 子树,并以相同的内容生成实例化的文档片段。
Contents
- 1 关于该文档
- 2 依赖关系
- 3 术语
- 4 介绍
- 5 定义
- 6 template元素
- 7 解析 HTML 模板
- 7.1 模板插入模式的栈
- 7.2 为一个令牌创建元素
- 7.3 附加一个模板
- 7.4 清除栈回到给定的上下文
- 7.5 附加的“收养”
- 7.6 附加的“适当的重置插入模式”
- 7.7 附加的“在表格范围内有一个元素”
- 7.8 附加的“head 内”插入模式
- 7.9 附加的“body 内”插入模式
- 7.10 附加的“表格内”插入模式
- 7.11 附加的“表格 body 内”插入模式
- 7.12 附加的“行内”插入模式
- 7.13 附加的“单元格内”插入模式
- 7.14 附加的“栏目组内”插入模式
- 7.15 附加的“select 内”插入模式
- 7.16 附加的“frameset 内”插入模式
- 7.17 “模板内容”插入模式
- 8 附加的解析 HTML 片段的步骤
- 9 附加的克隆一个节点的步骤
- 10 序列化 HTML 模板
- 11 模板上的 innerHTML
- 12 附加的解析 XHTML 文档
- 13 附加的序列化 XHTML 文档
- 14 展现模板元素时 XSLT 和 XPath 的行为
- 15 附加的 CSS 用户代理样式表
- 16 致谢
关于该文档
所有的图表、示例、注解都是非规范性的,同样每个章节的显性标记也是非规范性的。其余内容都是规范性的。
该文档的规范性内容中的“必须”、“必须不”、“要求”、“应该”、“不应该”、“推荐”、“可以”、“可选”关键字是如 RFC2119 中的描述进行解释。出于阅读体验的考虑,这些字不会在该规范中以全大写格式出现。
为了分层帮助并回避规范中不同部分之间的循环依赖,该文档由三大部分构成:
- 搭建起该规范的舞台
- 概念化模型的解释和背后的算法
- 通过 HTML 元素和 DOM 接口将这个模型表达出来
从某种意义上说,这几个部分可以视为数学层面:搭建推理的环境;物理层面:对于概念的理论推理;机械层面:关于这一推理的实践应用。
任何一个合格的用户代理必须为概念化模型的一个状态决定其自身的状态或反应,都会被捕获为算法。算法从运行等价的角度被定义。运行等价是指被约束执行这一算法的实现者,这对于所有输入来说,用户代理实现的算法和定义的算法都会得到完全一致的输出。
依赖关系
该文档依赖于如下规范:
术语
以下是本规范中用到的术语:
- 上下文对象 (context object)
- 调用我们讨论到的方法或特性的对象
- DOM
- 文档对象模型
- 文档 (document)
- DOM的基础文档
- 节点 (node)
- 任一树中的 DOM 对象
- 文档片段 (document fragment)
- 一个实现了
DocumentFragment
接口的 DOM 对象 - 元素 (element)
- 一个实现了
Element
接口的 DOM 对象 - DOM 树
- 任何由 DOM 对象组成的树
介绍
本章节是非规范性的
如今的很多网页都动态的改变文档内容 (比如响应用户交互或服务器传来的数据)。通常这样的网页在特定的情况下就需要用到 HTML 片段,这些片段可能在以后会被修改,比如根据使用情况插入适当的值。
我们希望有一种原型形式的标记片段声明,它可以在需要用到的时刻才被文档序列化和反序列化,HTML 目前尚未提供这种机制。因此,开发者们会隐藏这些片段,这样内容在一开始就生成同时能被浏览器忽略。这些片段通常是通过这几种方式完成的:
- 标记 (内联于文档),但设置 “display:none” 的样式。
- 字符串 (比如放在一个 <script> 块中)。
前者的缺陷在于开发者必须留意这个片段可能产生的副作用,比如根据尚未加工完毕的 URL 请求资源;而后者的缺陷在于它鼓励运行时以字符串形式解析 (通过 innerHTML) 用户提供的数据,这给 XSS 攻击提供了机会。另外两者都有一个无法解决的问题,就是它们都很难在顶级包含那些只能在特定元素下的元素 (比如 <tr> 或 <td>)。
本规范定义了 HTML 模板元素,这种元素用来声明那些在文档加载初期用不到,但是被解析为 HTML,在运行时可根据网页的使用而变化的文档片段。
<template> 元素可以放在 <head>、<body> 和 <frameset> 元素中,并且其内容可以包含 <head>、<body> 和 <frameset> 元素任何路径下可以包含的任何的任何内容。模板的内容并不是文档的一部分 (它们不会被显示,也不匹配任何 querySelector 等等) 并且是非活跃的 (比如不会导致资源加载、脚本运行、视频播放等等)。
定义
模板 (template) 提供了一个声明 HTML 文档片段的方法。被模板声明而来的文档片段被称作模板内容 (template contents)。
模板内容拥有者 (template contents owner) 是一个没有浏览器上下文的文档
每个文档都有一个相关联的模板内容拥有者,其等价的初始化步骤如下:
- 输入
- DOCUMENT,也就是文档
- 输出
- TEMPLATE CONTENTS OWNER,也就是模板内容拥有者
- 如果 DOCUMENT 没有浏览器上下文,则令 TEMPLATE CONTENTS OWNER 成为 DOCUMENT 并终止运行。
- 否则,令 TEMPLATE CONTENTS OWNER 成为一个新的没有浏览器上下文的文档结点。
- 如果 DOCUMENT 是一个 HTML 文档,则把 TEMPLATE CONTENTS OWNER 标记为 HTML 文档。
模板内容必须是一个文档片段,同时这个文档片段的结点文档是一个模板内容拥有者。
当解析的时候,如果开放元素栈有一个 template
元素且这个元素在其特定范围内由下面的元素类型组成:
-
html
Any
则它也会拥有一个 HTML 范围内的模板元素。
在解析章节的算法中模板内容案例被标记的部分,只会发生在以片段解析算法为目的或存在一个 HTML 范围内的模板元素的解析器被创建时 (解析器目前解析的是模板内容)。
template
元素
template
元素代表一个模板。
- 上下文
- 一个 head 元素的后代、一个 body 元素的后代、一个 frameset 元素的后代
- 内容模型
- 除 html 元素、head 元素、body 元素、frameset 元素以外的任何元素
- 内容特性
- 所有全局特性
- DOM 接口
interface HTMLTemplateElement : HTMLElement { readonly attribute DocumentFragment content; }
- 特性
-
content
-DocumentFragment
类型,只读:提供模板内容的访问。
-
在第一次访问之前,content
属性必须以下列等价步骤进行初始化:
- 输入
- TEMPLATE,也就是模板
- 输出
- CONTENTS,也就是模板内容
- 令 DOCUMENT 为上下文对象的文档节点的模板内容所有者。
- 令 CONTENTS 为一个新的文档片段对象,这个对象的文档节点是 DOCUMENT 并关联宿主元素是 TEMPLATE。
当一个模板对象的文档结点改变了,模板元素的 content
文档片段必须被新文档节点的模板内容所有者文档所领养。
非规范性提示:建议用户代理实现模板元素的时候屏蔽 DOM 继承圈,包括含有从模板元素到模板文档片段的引用。当这样的圈形成时,推荐用户代理抛出一个 HierarchyRequestError。
解析 HTML 模板
解析模板被定义为很多附加的HTML解析算法的集合。当解析的时候,template
元素在一个特殊的类别之中。
模板插入模式的栈
一开始,模板插入模式的栈是空的。这个栈会向下生长,栈的最上面是第一个压入栈的值,最下面是最近压入栈的值。
当前的模板插入模式是栈的最下面的节点。
为一个令牌创建元素
无论 HTML 解析器何时会为令牌创建一个元素,只要当前节点是一个模板元素,则该元素被创建的同时,会伴随其所有者文档被创建。该所有者文档会作为该模板元素的所有者文档的模板内容所有者。
附加一个模板
无论 HTML 解析器何时附加一个节点到一个模板元素,该节点必须以被附加到其模板元素的模板内容中而代之。
所以结论是,HTML 解析器永远不会直接放入任何节点作为子节点。
清除栈回到给定的上下文
当从开放元素栈中弹栈出元素时,如果当前节点是模板,则一个一致性的用户代理必须终止下面程序:
- 清除栈回给一个 table 上下文
- 清除栈回给一个 table body 上下文
- 清除栈回给一个 table row 上下文
附加的“收养”
当一个节点被收养时,如果开放元素栈中拥有一个模板元素,则其下最后一个不含 table 元素的模板元素是收养父元素 (不是模板的父亲)。否则应用常规的收养规则。
这样做是为了防止 HTML 解析器在一个节点被收养的时候,把模板里的内容“拿”出去,而令模板行为更接近 HTML 片段解析算法。
附加的“适当的重置插入模式”
在适当的重置插入模式算法中被标明“Loop”的步骤之后,加入以下步骤:
4. 如果节点是一个模板元素,则转换插入模式到当前模板插入模式并终止运行。
修改以“如果节点是 head 元素……”开头的步骤为:
11. 如果节点是 head 元素并且节点是上下文元素,则切换插入模式到“body 内” (“body 内”不是“head 内”) 并终止运行 (片段的情况)。否则切换插入模式到“head 内”,并终止运行。
下列情况之前被注明为片段的情况,现在可以在正常解析 (不只是片段的情况) 时进入且立刻跟随一个 &lr;/template<,并且这个注明应该被拿掉:
- 步骤4:“如果节点是一个 select 元素……”
- 步骤9:“如果节点是一个 colgroup 元素……”
- 步骤13:“如果节点是一个 frameset 元素……”
附加的“在表格范围内有一个元素”
为在一个表格范围内拥有一个元素的算法的元素类型列表中加入:
- HTML 命名空间中的
template