1

我有完全相同的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. 如果它被用作Content-Type application/xhtml+xml那么它们都是空的。无论有没有shadowDom.

如果我有

this.shadowRoot.innerHTML = `hello world`;

然后我得到了hello world。我在 FF 和 Chrome 上都得到了完全相同的行为,所以它看起来像预期的那样工作 - 这是在哪里记录的?

是不是因为浏览器 DOM API 不再是 html5 DOM 并变成 XML DOM,这意味着它不再可能分配给innerHTML,并且需要使用诸如DOMParser等工具?

4

1 回答 1

1

这与 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 = `&lt;p>hello world&lt;/p>`;
    }
}
customElements.define('hello-world', HelloWorld)
</script>
</body>
</html>

但相反的兼容性适用。它将在application/xhtml+xml内容类型中按需要工作,但会将标签解释为text/html内容类型中的文本。

如果你真的需要双语行为和 HTML 文件中的所有内容,你可以使用“to end-of-line-commented CDATA hack”。IE

<!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 真的不再是一回事了。只需选择您喜欢的内容类型即可。

于 2021-02-05T15:00:54.343 回答