xhtml 与 html5 本机 Web 组件行为
xhtml vs html5 native web component behaviour
我的一模一样html:
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Document</title>
</head>
<body>
<hello-world></hello-world>
<script>
class HelloWorld extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.shadowRoot.innerHTML = `<p>hello world</p>`;
}
}
customElements.define('hello-world', HelloWorld)
</script>
</body>
</html>
如果文件以 Content-Type text/html; charset=UTF-8
形式提供,这在 FF 和 Chrome 中都符合我的预期。如果它作为 Content-Type application/xhtml+xml
提供,那么它们都是空的。无论有无 shadowDom
.
,我似乎都会得到相同的行为
如果我有
this.shadowRoot.innerHTML = `hello world`;
然后我得到hello world
。我在 FF 和 Chrome 上得到完全相同的行为,所以它看起来像预期的那样工作 - 这在哪里记录?
是不是因为浏览器的 DOM API 不再是 html5 DOM 而变成了 XML DOM,这意味着不再可能分配给 innerHTML
,并且需要使用DOMParser
等工具?
这与 XML 解析器的工作方式有关。 <p>...</p>
标签被 XML 解析器解析为 元素 而不是像 HTML 解析器那样解析为文本,因此 p
元素及其内容绝不是输入到 .innerHTML.
的字符串的一部分
如果您将 JavaScript 提取到外部文件,然后引用它,那么它工作正常,因为 JavaScript 不会被传递给 HTML/XML 解析器。
或者,您可以转义 <
个字符。所以
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Document</title>
</head>
<body>
<hello-world></hello-world>
<script>
class HelloWorld extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.shadowRoot.innerHTML = `<p>hello world</p>`;
}
}
customElements.define('hello-world', HelloWorld)
</script>
</body>
</html>
相反的兼容性适用。它将在 application/xhtml+xml
内容类型中按需要工作,但会将标签解释为 text/html
内容类型中的文本。
如果您确实需要双语行为和 HTML 文件中的所有内容,您可以使用“行尾注释 CDATA hack”。即
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Document</title>
</head>
<body>
<hello-world></hello-world>
<script>
//<![CDATA[
class HelloWorld extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.shadowRoot.innerHTML = `<p>hello world</p>`;
}
}
customElements.define('hello-world', HelloWorld)
//]]>
</script>
</body>
</html>
然而,双语 HTML 真的不再是一回事了。只需选择您喜欢的内容类型即可。
我的一模一样html:
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Document</title>
</head>
<body>
<hello-world></hello-world>
<script>
class HelloWorld extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.shadowRoot.innerHTML = `<p>hello world</p>`;
}
}
customElements.define('hello-world', HelloWorld)
</script>
</body>
</html>
如果文件以 Content-Type text/html; charset=UTF-8
形式提供,这在 FF 和 Chrome 中都符合我的预期。如果它作为 Content-Type application/xhtml+xml
提供,那么它们都是空的。无论有无 shadowDom
.
如果我有
this.shadowRoot.innerHTML = `hello world`;
然后我得到hello world
。我在 FF 和 Chrome 上得到完全相同的行为,所以它看起来像预期的那样工作 - 这在哪里记录?
是不是因为浏览器的 DOM API 不再是 html5 DOM 而变成了 XML DOM,这意味着不再可能分配给 innerHTML
,并且需要使用DOMParser
等工具?
这与 XML 解析器的工作方式有关。 <p>...</p>
标签被 XML 解析器解析为 元素 而不是像 HTML 解析器那样解析为文本,因此 p
元素及其内容绝不是输入到 .innerHTML.
如果您将 JavaScript 提取到外部文件,然后引用它,那么它工作正常,因为 JavaScript 不会被传递给 HTML/XML 解析器。
或者,您可以转义 <
个字符。所以
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Document</title>
</head>
<body>
<hello-world></hello-world>
<script>
class HelloWorld extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.shadowRoot.innerHTML = `<p>hello world</p>`;
}
}
customElements.define('hello-world', HelloWorld)
</script>
</body>
</html>
相反的兼容性适用。它将在 application/xhtml+xml
内容类型中按需要工作,但会将标签解释为 text/html
内容类型中的文本。
如果您确实需要双语行为和 HTML 文件中的所有内容,您可以使用“行尾注释 CDATA hack”。即
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Document</title>
</head>
<body>
<hello-world></hello-world>
<script>
//<![CDATA[
class HelloWorld extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
}
connectedCallback() {
this.shadowRoot.innerHTML = `<p>hello world</p>`;
}
}
customElements.define('hello-world', HelloWorld)
//]]>
</script>
</body>
</html>
然而,双语 HTML 真的不再是一回事了。只需选择您喜欢的内容类型即可。