Web 开发者版 — 最后更新于 2024 年 9 月 12 日
脚本允许作者向其文档添加交互性。
鼓励作者尽可能使用声明式替代脚本,因为声明式机制通常更易于维护,并且许多用户禁用了脚本。
例如,与其使用脚本显示或隐藏某个部分以显示更多详细信息,不如使用 details
元素。
还鼓励作者在没有脚本支持的情况下使他们的应用程序优雅降级。
例如,如果作者在表格标题中提供一个链接以动态重新排序表格,则该链接也可以在没有脚本的情况下工作,方法是从服务器请求排序后的表格。
script
元素所有当前引擎都支持。
src
属性,则取决于 type
属性的值,但必须与 脚本内容限制 匹配。src
属性,则该元素必须为空或仅包含也与 脚本内容限制 匹配的 脚本文档。src
— 资源的地址type
— 脚本类型nomodule
— 阻止支持 模块脚本 的用户代理执行async
— 在可用时执行脚本,在获取时不阻塞defer
— 延迟脚本执行crossorigin
— 元素如何处理跨源请求integrity
— 用于 子资源完整性 检查中的完整性元数据 [SRI]referrerpolicy
— 元素发起的 获取 的 引用者策略blocking
— 元素是否 可能阻塞渲染fetchpriority
— 设置元素发起的 获取 的 优先级HTMLScriptElement
。script
元素允许作者在其文档中包含动态脚本和数据块。该元素不 代表用户的内容。
所有当前引擎都支持。
type
属性允许自定义表示的脚本类型
省略该属性、将其设置为空字符串或将其设置为 JavaScript MIME 类型本质匹配,表示该脚本是 经典脚本,将根据 JavaScript Script 顶级生成进行解释。经典脚本受 async
和 defer
属性的影响,但仅当设置了 src
属性时才受影响。作者应省略 type
属性,而不是冗余地设置它。
将属性设置为 "module
" 的 ASCII 不区分大小写 匹配,表示该脚本是 JavaScript 模块脚本,将根据 JavaScript Module 顶级生成进行解释。模块脚本不受 defer
属性的影响,但受 async
属性的影响(无论 src
属性的状态如何)。
将属性设置为 "importmap
" 的 ASCII 不区分大小写 匹配,表示该脚本是 导入映射,包含将用于控制 模块说明符解析 行为的 JSON。导入映射只能是内联的,即 src
属性和大多数其他属性在此处毫无意义,不应与它们一起使用。
将属性设置为任何其他值,表示该脚本是 数据块,不会被处理。没有一个 script
属性(除了 type
本身)对数据块有任何影响。作者必须使用不是 JavaScript MIME 类型本质匹配 的 有效的 MIME 类型字符串 来表示数据块。
使用 有效的 MIME 类型字符串 表示 数据块 的要求是为了避免潜在的未来冲突。如果此规范将来添加其他类型的 脚本,则可以通过将 type
属性设置为非 MIME 类型的值来触发它们,例如 "module
" 值表示 模块脚本。通过现在使用有效的 MIME 类型字符串,可以确保数据块永远不会被重新解释为其他脚本类型,即使在未来的用户代理中也是如此。
经典脚本 和 JavaScript 模块脚本 可以内联嵌入,也可以使用 src
属性从外部文件导入,如果指定了该属性,则表示要使用的外部脚本资源的 URL。如果指定了 src
,则它必须是 有效的非空 URL,可能由空格包围。
内联 script
元素的内容或外部脚本资源必须符合 JavaScript 规范的 Script 或 Module 生成(分别针对 经典脚本 和 JavaScript 模块脚本)的要求。 [JAVASCRIPT]
CSS 模块脚本 的外部脚本资源的内容必须符合 CSS 规范的要求。 [CSS]
JSON 模块脚本 的外部脚本资源的内容必须符合 JSON 规范的要求。 [JSON]
导入映射 的内联 script
元素的内容必须符合 导入映射创作要求。
对于 导入映射 script
元素,src
、async
、nomodule
、defer
、crossorigin
、integrity
和 referrerpolicy
属性不得指定。
当用于包含数据块时,数据必须嵌入内联,数据的格式必须使用type
属性给出,并且script
元素的内容必须符合为所用格式定义的要求。src
、async
、nomodule
、defer
、crossorigin
、integrity
、referrerpolicy
和fetchpriority
属性不得指定。
nomodule
属性是一个布尔属性,它阻止在支持模块脚本的用户代理中执行脚本。这允许在现代用户代理中选择性地执行模块脚本,在旧版用户代理中执行经典脚本,如下所示。nomodule
属性不得在模块脚本上指定(如果指定,则会被忽略)。
所有当前引擎都支持。
所有当前引擎都支持。
async
和defer
属性是布尔属性,指示如何评估脚本。经典脚本可以指定defer
或async
,但除非存在src
属性,否则不得指定两者。模块脚本可以指定async
属性,但不得指定defer
属性。
有几种可能的模式可以使用这些属性进行选择,具体取决于脚本的类型。
对于经典脚本,如果存在async
属性,则经典脚本将并行于解析进行获取,并在可用时立即进行评估(可能在解析完成之前)。如果不存在async
属性,但存在defer
属性,则经典脚本将并行获取,并在页面完成解析后进行评估。如果两个属性都不存在,则脚本将立即获取和评估,阻塞解析直到两者都完成。
对于模块脚本,如果存在async
属性,则模块脚本及其所有依赖项将并行于解析进行获取,并且模块脚本将在可用时立即进行评估(可能在解析完成之前)。否则,模块脚本及其所有依赖项将并行于解析进行获取,并在页面完成解析后进行评估。(defer
属性对模块脚本没有影响。)
所有这些都总结在下图中
出于历史原因,这些属性的确切处理细节有些复杂,涉及 HTML 的许多方面。因此,实现要求必然分散在规范的各个部分。以下算法(在本节中)描述了此处理的核心,但这些算法引用并被 HTML 中script
开始和结束标签的解析规则、在外部内容中和在 XML 中的解析规则、document.write()
方法的规则、脚本编写的处理等引用和引用。
使用document.write()
方法插入时,script
元素通常执行(通常阻塞进一步的脚本执行或 HTML 解析)。使用innerHTML
和outerHTML
属性插入时,它们根本不会执行。
即使指定了async
属性,也可以指定defer
属性,以使仅支持defer
(而不是async
)的旧版 Web 浏览器回退到defer
行为,而不是默认的阻塞行为。
crossorigin
属性是CORS 设置属性。对于经典脚本,它控制何时从其他来源获取脚本时是否会公开错误信息。对于模块脚本,它控制用于跨源请求的凭据模式。
与经典脚本不同,模块脚本要求使用CORS 协议进行跨源获取。
integrity
属性表示此元素负责的请求的完整性元数据。该值为文本。integrity
属性不得在未指定src
属性时指定。[SRI]
referrerpolicy
属性是引用者策略属性。其目的是设置引用者策略,用于获取脚本以及从中导入的任何脚本。[REFERRERPOLICY]
一个script
元素的引用者策略在获取导入的脚本时使用,但在获取其他子资源时不使用。
< script referrerpolicy = "origin" >
fetch( '/api/data' ); // not fetched with <script>'s referrer policy
import ( './utils.mjs' ); // is fetched with <script>'s referrer policy ("origin" in this case)
</ script >
blocking
属性是阻塞属性。
fetchpriority
属性是获取优先级属性。其目的是设置优先级,用于获取脚本。
动态更改src
、type
、nomodule
、async
、defer
、crossorigin
、integrity
、referrerpolicy
和fetchpriority
属性没有直接影响;这些属性仅在下面描述的特定时间使用。
script.text [ = value ]
返回元素的子文本内容。
可以设置,以使用给定值替换元素的子元素。
HTMLScriptElement
.supports(type)
HTMLScriptElement/supports_static
所有当前引擎都支持。
如果给定的type是用户代理支持的脚本类型,则返回 true。此规范中可能的脚本类型为“classic
”、“module
”和“importmap
”,但将来可能会添加其他类型。
type参数必须完全匹配这些值;我们不执行ASCII 不区分大小写匹配。这与type
内容属性值的处理方式以及DOMTokenList
的supports()
方法的工作方式不同,但它与Worker()
构造函数中使用的WorkerType
枚举一致。
在此示例中,使用了两个script
元素。一个嵌入外部经典脚本,另一个包含一些数据作为数据块。
< script src = "game-engine.js" ></ script >
< script type = "text/x-game-map" >
........ U......... e
o............ A.... e
..... A..... AAA.... e
. A.. AAA... AAAAA... e
</ script >
在这种情况下,数据可能会被脚本用于生成视频游戏的映射。不过,数据不必以这种方式使用;也许地图数据实际上嵌入在页面标记的其他部分,而此处的数据库块仅由站点的搜索引擎用于帮助寻找游戏中特定功能的用户。
以下示例演示了如何使用`script
` 元素定义一个函数,然后作为`传统脚本`的一部分,由文档的其他部分使用。它还演示了如何使用`script
` 元素在解析文档时调用脚本,在本例中用于初始化表单的输出。
< script >
function calculate( form) {
var price = 52000 ;
if ( form. elements. brakes. checked)
price += 1000 ;
if ( form. elements. radio. checked)
price += 2500 ;
if ( form. elements. turbo. checked)
price += 5000 ;
if ( form. elements. sticker. checked)
price += 250 ;
form. elements. result. value = price;
}
</ script >
< form name = "pricecalc" onsubmit = "return false" onchange = "calculate(this)" >
< fieldset >
< legend > Work out the price of your car</ legend >
< p > Base cost: £52000.</ p >
< p > Select additional options:</ p >
< ul >
< li >< label >< input type = checkbox name = brakes > Ceramic brakes (£1000)</ label ></ li >
< li >< label >< input type = checkbox name = radio > Satellite radio (£2500)</ label ></ li >
< li >< label >< input type = checkbox name = turbo > Turbo charger (£5000)</ label ></ li >
< li >< label >< input type = checkbox name = sticker > "XZ" sticker (£250)</ label ></ li >
</ ul >
< p > Total: £< output name = result ></ output ></ p >
</ fieldset >
< script >
calculate( document. forms. pricecalc);
</ script >
</ form >
以下示例演示了如何使用`script
` 元素包含一个外部`JavaScript 模块脚本`。
< script type = "module" src = "app.mjs" ></ script >
此模块及其所有依赖项(在源文件中通过 JavaScript `import` 语句表示)将被获取。一旦整个生成的模块图被导入,并且文档解析完成,`app.mjs` 的内容将被评估。
此外,如果来自同一 `Window` 中另一个`script
` 元素的代码导入来自 `app.mjs` 的模块(例如,通过 `import "./app.mjs";`),则将导入由前一个`script
` 元素创建的相同`JavaScript 模块脚本`。
此示例演示了如何为现代用户代理包含`JavaScript 模块脚本`,以及为旧版用户代理包含`传统脚本`。
< script type = "module" src = "app.mjs" ></ script >
< script nomodule defer src = "classic-app-bundle.js" ></ script >
在支持`JavaScript 模块脚本`的现代用户代理中,带有`nomodule
` 属性的`script
` 元素将被忽略,而`type
` 为“`module`”的`script
` 元素将被获取和评估(作为`JavaScript 模块脚本`)。相反,旧版用户代理将忽略`type
` 为“`module`”的`script
` 元素,因为这对它们来说是一种未知的脚本类型——但它们在获取和评估另一个`script
` 元素(作为`传统脚本`)时没有任何问题,因为它们没有实现`nomodule
` 属性。
以下示例演示了如何使用`script
` 元素编写一个内联`JavaScript 模块脚本`,该脚本对文档的文本执行一系列替换,以获得更有趣的阅读体验(例如,在新闻网站上):[XKCD1288]
< script type = "module" >
import { walkAllTextNodeDescendants } from "./dom-utils.mjs" ;
const substitutions = new Map([
[ "witnesses" , "these dudes I know" ]
[ "allegedly" , "kinda probably" ]
[ "new study" , "Tumblr post" ]
[ "rebuild" , "avenge" ]
[ "space" , "spaaace" ]
[ "Google glass" , "Virtual Boy" ]
[ "smartphone" , "Pokédex" ]
[ "electric" , "atomic" ]
[ "Senator" , "Elf-Lord" ]
[ "car" , "cat" ]
[ "election" , "eating contest" ]
[ "Congressional leaders" , "river spirits" ]
[ "homeland security" , "Homestar Runner" ]
[ "could not be reached for comment" , "is guilty and everyone knows it" ]
]);
function substitute( textNode) {
for ( const [ before, after] of substitutions. entries()) {
textNode. data = textNode. data. replace( new RegExp( `\\b ${ before} \\b` , "ig" ), after);
}
}
walkAllTextNodeDescendants( document. body, substitute);
</ script >
使用 JavaScript 模块脚本获得的一些显著功能包括:能够从其他 JavaScript 模块导入函数,默认情况下使用严格模式,以及顶级声明不会在`全局对象`上引入新属性。另请注意,无论此`script
` 元素出现在文档中的哪个位置,它都不会在文档解析完成并且其依赖项(`dom-utils.mjs`)被获取并评估之前进行评估。
以下示例演示了如何从`JavaScript 模块脚本`内部导入`JSON 模块脚本`。
< script type = "module" >
import peopleInSpace from "http://api.open-notify.org/astros.json" with { type: "json" };
const list = document. querySelector( "#people-in-space" );
for ( const { craft, name } of peopleInSpace. people) {
const li = document. createElement( "li" );
li. textContent = ` ${ name} / ${ craft} ` ;
list. append( li);
}
</ script >
模块脚本的 MIME 类型检查非常严格。为了使`JSON 模块脚本`的获取成功,HTTP 响应必须具有JSON MIME 类型,例如 `Content-Type: text/json`。另一方面,如果省略了语句中的 `with { type: "json" }` 部分,则假定意图是导入`JavaScript 模块脚本`,如果 HTTP 响应的 MIME 类型不是JavaScript MIME 类型,则获取将失败。
服务器应根据《ECMAScript 媒体类型更新》为 JavaScript 资源使用`text/javascript
`。服务器不应为 JavaScript 资源使用其他JavaScript MIME 类型,并且不得使用非JavaScript MIME 类型。[RFC9239]
script
元素内容的限制`避免本节中描述的相当奇怪的限制的最简单、最安全的方法是始终将 ASCII 不区分大小写的“`<!--`”匹配转义为“`\x3C!--`”,“`<script`”转义为“`\x3Cscript`”,“`</script`”转义为“`\x3C/script`”,当这些序列出现在脚本的字面量中时(例如,在字符串、正则表达式或注释中),并避免编写使用此类构造的代码。这样做可以避免本节中的限制容易触发的陷阱:即,由于历史原因,HTML 中`script
` 块的解析是一种奇怪且奇特的做法,在遇到这些序列时会表现得反直觉。
`script
` 元素的后代文本内容必须匹配以下 ABNF 中的 `script` 产生式,其字符集为 Unicode。[ABNF]
script = outer * ( comment-open inner comment-close outer )
outer = < any string that doesn 't contain a substring that matches not-in-outer >
not-in-outer = comment-open
inner = < any string that doesn 't contain a substring that matches not-in-inner >
not-in-inner = comment-close / script-open
comment-open = "<!--"
comment-close = "-->"
script-open = "<" s c r i p t tag-end
s = %x0053 ; U+0053 LATIN CAPITAL LETTER S
s =/ %x0073 ; U+0073 LATIN SMALL LETTER S
c = %x0043 ; U+0043 LATIN CAPITAL LETTER C
c =/ %x0063 ; U+0063 LATIN SMALL LETTER C
r = %x0052 ; U+0052 LATIN CAPITAL LETTER R
r =/ %x0072 ; U+0072 LATIN SMALL LETTER R
i = %x0049 ; U+0049 LATIN CAPITAL LETTER I
i =/ %x0069 ; U+0069 LATIN SMALL LETTER I
p = %x0050 ; U+0050 LATIN CAPITAL LETTER P
p =/ %x0070 ; U+0070 LATIN SMALL LETTER P
t = %x0054 ; U+0054 LATIN CAPITAL LETTER T
t =/ %x0074 ; U+0074 LATIN SMALL LETTER T
tag-end = %x0009 ; U+0009 CHARACTER TABULATION (tab)
tag-end =/ %x000A ; U+000A LINE FEED (LF)
tag-end =/ %x000C ; U+000C FORM FEED (FF)
tag-end =/ %x0020 ; U+0020 SPACE
tag-end =/ %x002F ; U+002F SOLIDUS (/)
tag-end =/ %x003E ; U+003E GREATER-THAN SIGN (>)
当`script
` 元素包含脚本文档时,对元素的内容还有其他限制,如下面的部分所述。
以下脚本说明了此问题。假设您有一个包含字符串的脚本,如下所示
const example = 'Consider this string: <!-- <script>' ;
console. log( example);
如果将此字符串直接放在`script
` 块中,它将违反上述限制。
< script >
const example = 'Consider this string: <!-- <script>' ;
console. log( example);
</ script >
不过,更大的问题,也是它违反这些限制的原因在于,脚本实际上会被奇怪地解析:上面的脚本块没有终止。也就是说,此代码段中看起来像“`</script>`”结束标记的实际上仍然是`script
` 块的一部分。脚本不会执行(因为它没有终止);如果它以某种方式执行,就像标记如下所示时可能发生的那样,它将失败,因为脚本(此处突出显示)不是有效的 JavaScript。
< script >
const example = 'Consider this string: <!-- <script>' ;
console. log( example);
</ script >
<!-- despite appearances, this is actually part of the script still! -->
< script >
... // this is the same script block still...
</ script >
这里发生的情况是,出于遗留原因,HTML 中`script
` 元素中的“`<!--`”和“`<script`”字符串需要平衡,才能使解析器认为关闭了块。
通过按照本节开头提到的方式转义有问题的字符串,可以完全避免此问题。
< script >
// Note: `\x3C` is an escape sequence for `<`.
const example = 'Consider this string: \x3C!-- \x3Cscript>' ;
console. log( example);
</ script >
<!-- this is just a comment between script blocks -->
< script >
... // this is a new script block
</ script >
这些序列可能自然出现在脚本表达式中,例如以下示例
if ( x<!-- y) { ... }
if ( player< script ) { ... }
在这种情况下,无法转义这些字符,但可以重写表达式以使这些序列不出现,如下所示
if ( x < !-- y) { ... }
if ( !-- y > x) { ... }
if ( ! ( -- y) > x) { ... }
if ( player < script) { ... }
if ( script > player) { ... }
这样做还可以避免另一个陷阱:出于相关历史原因,`传统脚本`中的字符串“`<!--`”实际上被视为行注释的开始,就像“`//`”一样。
如果`script
` 元素的`src
` 属性已指定,则`script
` 元素的内容(如果有)必须使得`text
` IDL 属性的值(派生自元素的内容)匹配以下 ABNF 中的 `documentation` 产生式,其字符集为 Unicode。[ABNF]
documentation = * ( * ( space / tab / comment ) [ line-comment ] newline )
comment = slash star * ( not-star / star not-slash ) 1* star slash
line-comment = slash slash * not-newline
; characters
tab = %x0009 ; U+0009 CHARACTER TABULATION (tab)
newline = %x000A ; U+000A LINE FEED (LF)
space = %x0020 ; U+0020 SPACE
star = %x002A ; U+002A ASTERISK (*)
slash = %x002F ; U+002F SOLIDUS (/)
not-newline = %x0000-0009 / %x000B-10FFFF
; a scalar value other than U+000A LINE FEED (LF)
not-star = %x0000-0029 / %x002B-10FFFF
; a scalar value other than U+002A ASTERISK (*)
not-slash = %x0000-002E / %x0030-10FFFF
; a scalar value other than U+002F SOLIDUS (/)
这对应于将元素的内容放在 JavaScript 注释中。
此要求是对之前关于`script
` 元素内容语法的限制的补充。
这允许作者在文档中包含文档,例如许可证信息或 API 信息,同时仍然引用外部脚本文件。语法受到限制,以防止作者意外地包含看起来像有效脚本的内容,同时还提供`src
` 属性。
< script src = "cool-effects.js" >
// create new instances using:
// var e = new Effect();
// start the effect using .play, stop using .stop:
// e.play();
// e.stop();
</ script >
noscript
` 元素所有当前引擎都支持。
head
` 元素中,如果不存在祖先`noscript
` 元素,则在`HTML 文档`的`HTML 文档`中。noscript
` 元素,则预期`短语内容`。head
` 元素中:以任何顺序,零个或多个`link
` 元素,零个或多个`style
` 元素,以及零个或多个`meta
` 元素。head
` 元素中:`透明的`,但不得有`noscript
` 元素后代。如果`脚本已启用`,则`noscript
` 元素`表示`无,如果`脚本已禁用`,则`表示`其子元素。它用于通过影响文档的解析方式,向支持脚本的用户代理和不支持脚本的用户代理呈现不同的标记。
在`HTML 文档`中使用时,允许的内容模型如下
head
` 元素中,如果`noscript
` 元素的`脚本已禁用`
head
元素中,如果为 noscript
元素启用了脚本noscript
元素只能包含文本,但使用 noscript
元素作为 context 元素,文本内容作为 input 调用 HTML 片段解析算法必须生成一个节点列表,该列表仅包含 link
、style
和 meta
元素,如果它们是 noscript
元素的子元素,则这些元素必须符合规范,并且没有解析错误。
head
元素之外,如果为 noscript
元素禁用了脚本noscript
元素的内容模型是 透明的,并附加限制,即 noscript
元素不能具有 noscript
元素作为祖先(也就是说,noscript
不能嵌套)。
head
元素之外,如果为 noscript
元素启用了脚本noscript
元素只能包含文本,但文本必须满足以下条件:运行以下算法必须生成一个符合规范的文档,其中不包含 noscript
元素和 script
元素,并且算法中的任何步骤都不会引发异常或导致 HTML 解析器标记解析错误。
所有这些曲折都是必需的,因为由于历史原因,HTML 解析器根据解析器被调用时是否启用了脚本以不同的方式处理 noscript
元素。
noscript
元素仅在 HTML 语法 中有效,在 XML 语法 中无效。这是因为它通过在启用脚本时“关闭”解析器来工作,以便元素的内容被视为纯文本而不是实际元素。XML 没有定义执行此操作的机制。
在以下示例中,noscript
元素用于为脚本提供回退。
< form action = "calcSquare.php" >
< p >
< label for = x > Number</ label > :
< input id = "x" name = "x" type = "number" >
</ p >
< script >
var x = document. getElementById( 'x' );
var output = document. createElement( 'p' );
output. textContent = 'Type a number; it will be squared right then!' ;
x. form. appendChild( output);
x. form. onsubmit = function () { return false ; }
x. oninput = function () {
var v = x. valueAsNumber;
output. textContent = v + ' squared is ' + v * v;
};
</ script >
< noscript >
< input type = submit value = "Calculate Square" >
</ noscript >
</ form >
当脚本被禁用时,将显示一个按钮以在服务器端进行计算。当脚本启用时,将即时计算该值。
noscript
元素是一种笨拙的工具。有时,脚本可能已启用,但由于某种原因,页面的脚本可能会失败。因此,通常最好避免使用 noscript
,而是设计脚本以根据需要将页面从无脚本页面更改为有脚本页面,如下一个示例所示。
< form action = "calcSquare.php" >
< p >
< label for = x > Number</ label > :
< input id = "x" name = "x" type = "number" >
</ p >
< input id = "submit" type = submit value = "Calculate Square" >
< script >
var x = document. getElementById( 'x' );
var output = document. createElement( 'p' );
output. textContent = 'Type a number; it will be squared right then!' ;
x. form. appendChild( output);
x. form. onsubmit = function () { return false ; }
x. oninput = function () {
var v = x. valueAsNumber;
output. textContent = v + ' squared is ' + v * v;
};
var submit = document. getElementById( 'submit' );
submit. parentNode. removeChild( submit);
</ script >
</ form >
template
元素所有当前引擎都支持。
span
属性的 colgroup
元素的子元素。shadowrootmode
— 启用流式声明式阴影根shadowrootdelegatesfocus
— 在声明式阴影根上设置 委托焦点shadowrootclonable
— 在声明式阴影根上设置 可克隆shadowrootserializable
— 在声明式阴影根上设置可序列化HTMLTemplateElement
。template
元素用于声明 HTML 片段,这些片段可以通过脚本克隆并插入文档中。
shadowrootmode
内容属性是一个 枚举属性,具有以下关键字和状态
关键字 | 状态 | 简要说明 |
---|---|---|
open
| open | 模板元素表示一个开放的声明式阴影根。 |
closed
| closed | 模板元素表示一个封闭的声明式阴影根。 |
shadowrootmode
属性的 无效值默认值 和 缺失值默认值 均为 none 状态。
shadowrootdelegatesfocus
内容属性是一个 布尔属性。
shadowrootclonable
内容属性是一个 布尔属性。
shadowrootserializable
内容属性是一个 布尔属性。
template
元素的 模板内容 不是元素本身的子元素。
由于 DOM 操作,template
元素也可能包含 Text
节点和元素节点;但是,存在任何节点都违反了 template
元素的内容模型,因为其内容模型定义为 无。
例如,考虑以下文档
<!doctype html>
< html lang = "en" >
< head >
< title > Homework</ title >
< body >
< template id = "template" >< p > Smile!</ p ></ template >
< script >
let num = 3 ;
const fragment = document. getElementById( 'template' ). content. cloneNode( true );
while ( num-- > 1 ) {
fragment. firstChild. before( fragment. firstChild. cloneNode( true ));
fragment. firstChild. textContent += fragment. lastChild. textContent;
}
document. body. appendChild( fragment);
</ script >
</ html >
template
中的 p
元素 *不是* DOM 中 template
的子元素;它是 template
元素的 content
IDL 属性返回的 DocumentFragment
的子元素。
如果脚本要对 template
元素调用 appendChild()
,则会向 template
元素添加一个子元素(与任何其他元素一样);但是,这样做违反了 template
元素的内容模型。
template.content
返回 模板内容(一个 DocumentFragment
)。
在此示例中,脚本使用来自数据结构的数据填充一个四列表,使用 template
提供元素结构,而不是手动从标记生成结构。
<!DOCTYPE html>
< html lang = 'en' >
< title > Cat data</ title >
< script >
// Data is hard-coded here, but could come from the server
var data = [
{ name: 'Pillar' , color: 'Ticked Tabby' , sex: 'Female (neutered)' , legs: 3 },
{ name: 'Hedral' , color: 'Tuxedo' , sex: 'Male (neutered)' , legs: 4 },
];
</ script >
< table >
< thead >
< tr >
< th > Name < th > Color < th > Sex < th > Legs
< tbody >
< template id = "row" >
< tr >< td >< td >< td >< td >
</ template >
</ table >
< script >
var template = document. querySelector( '#row' );
for ( var i = 0 ; i < data. length; i += 1 ) {
var cat = data[ i];
var clone = template. content. cloneNode( true );
var cells = clone. querySelectorAll( 'td' );
cells[ 0 ]. textContent = cat. name;
cells[ 1 ]. textContent = cat. color;
cells[ 2 ]. textContent = cat. sex;
cells[ 3 ]. textContent = cat. legs;
template. parentNode. appendChild( clone);
}
</ script >
此示例对cloneNode()
应用于template
的内容;它也可以等效地使用document.importNode()
,它执行相同操作。这两个 API 之间的唯一区别在于何时更新节点文档:使用cloneNode()
时,在使用appendChild()
追加节点时更新;使用document.importNode()
时,在克隆节点时更新。
slot
元素所有当前引擎都支持。
name
— 阴影树插槽的名称HTMLSlotElement
。
元素定义了一个插槽。它通常用于阴影树中。一个slot
slot
元素表示其分配的节点(如果有)以及否则其内容。
属性用于分配插槽到其他元素:具有name
属性的name
slot
元素创建一个命名插槽,如果该元素具有一个值与该
属性值匹配的name
属性,则任何元素都将分配到该插槽,并且slot
元素是阴影树的子元素,其根的宿主具有相应的slot
属性值。slot
slot.name
slot.assignedNodes()
slot.assignedNodes({ flatten: true })
slot
元素递归执行相同的操作,直到没有剩余的slot
元素。slot.assignedElements()
slot.assignedElements({ flatten: true })
assignedNodes({ flatten: true })
相同的结果,仅限于元素。slot.assign(...nodes)
将slot的手动分配的节点设置为给定的nodes。
name
IDL 属性必须反映同名内容属性。
元素具有手动分配的节点,它是一个有序集合,由slot
设置的可插槽。此集合最初为空。assign()
可以使用对可插槽的弱引用来实现手动分配的节点集合,因为此集合无法从脚本直接访问。
assignedNodes(options)
方法的步骤是
assignedElements(options)
方法的步骤是
所有当前引擎都支持。
assign(...nodes)
方法的步骤是