【问题标题】:Can fetch be used to replace the entire document or html element?fetch可以用来替换整个文档或者html元素吗?
【发布时间】:2020-12-15 21:19:21
【问题描述】:

在一个网络扩展中,我一直将背景页面中的模板元素作为字符串传递给一个空的本地 HTML 文件,并使用 browser.tabs.insertCSSbrowser.tabs.executeScript 传递 CSS 和 JS。这一直运作良好,但我最近了解到 fetch 可用于直接从扩展程序中检索文件,这将减少后台页面的大小或完全消除它,只留下后台脚本并减少 RAM 使用。

我在SO question 中看到了一些使用innerHTML 将HTML 字符串写入body 元素的示例,还有一个使用DOMParser. 的示例,但是如果您尝试一下,HTML 会添加到body 元素中。

另一个SO question,10 岁,有一个 5 岁的最后回应很有趣,反正对于像我这样的新手来说;我试过了,这似乎有效。

fetch('file.html')
.then( response => response.text() )
.then( result => {
        let parser = new DOMParser(),
            doc = parser.parseFromString( result, 'text/html' );
        document.replaceChild( doc.documentElement, document.documentElement );
    } );

我的问题是,这是完全替换 html 元素的有效且可靠的方法吗?

谢谢。

【问题讨论】:

  • 你的 javascript 事件处理程序等会发生什么,
  • 我可以在检查器中看到 HTML 文档附带了脚本标签,但事件在我的小测试文件中不起作用。感谢您指出了这一点。我想我需要弄清楚如何使脚本运行或仍然通过扩展注入它。
  • 脚本标签显示在检查器中,但源数据仍然是旧的 html 和脚本。

标签: javascript html dom


【解决方案1】:

没有。在某些情况下,这会产生意想不到的副作用。

这里有一个简单的例子来说明这一点:

index.html

<html>
<head>
  <title>DOM Parser test</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <h1>This is the original file</h1>
  <button id="btn1" type="button">Click to reload</button>

  <script>
    var btn1 = document.getElementById('btn1');
    function onClick() {
      fetch('file.html')
       .then( response => response.text() )
       .then( result => {
          let parser = new DOMParser();
          doc = parser.parseFromString( result, 'text/html' );
          document.replaceChild( doc.documentElement, document.documentElement );
        } );
    }

    btn1.addEventListener('click', onClick);
  </script>
</body>
</html>

文件.html

<html>
<head>
  <title>DOM Parser test</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <h1>This is the second file</h1>
  <button id="btn1" type="button">Click to reload</button>

  <script>
    var btn1 = document.getElementById('btn1');
    function onClick() {
      fetch('file.html')
       .then( response => response.text() )
       .then( result => {
          let parser = new DOMParser();
          doc = parser.parseFromString( result, 'text/html' );
          document.replaceChild( doc.documentElement, document.documentElement );
        } );
    }

    btn1.addEventListener('click', onClick);
  </script>
</body>
</html>

style.css

html body {
      background: #00003f;
}

我使用节点 JS http-server ./ 提供这些静态文件并访问了 index.html

现在单击“单击以重新加载”按钮。这应该获取 file.html 并呈现它。

在 index.html 和 file.html 的源代码中可以看到,它们都引用了 style.css 样式表。 index.html 渲染了引用的样式,而获取并用于更新 documentElement 的 file.html 不支持样式表。

这是事情如何破裂的一个例子。

【讨论】:

  • 谢谢你的例子。这很有趣,为我省去了很多麻烦,可能浪费了几个小时,以为我只是在扩展程序中做错了什么。使用 fetch 仅获取其他 DOM 元素内容是否安全,这些内容将通过后台页面中的模板元素提供,然后通过 browser.tab 方法添加 CSS 和 JS?
  • 我一直在使用insertAdjacentHTML 将模板添加为字符串,因为无法将 DOM 节点从后台传递到页面。也许这些模板可以是扩展中的单独 HTML 文件,以便可以获取、解析并用于替换 body 元素或 body 元素的内容,之后浏览器选项卡方法可以添加 CSS 和 JS。这仍然可以减少背景 HTML 页面的大小或删除。
  • 是的。如果要插入需要遵守全局上下文的组件,则 insertAdjacentHTML;如果要使用自包含组件,则插入 Shadow DOM(请参阅:developer.mozilla.org/en-US/docs/Web/Web_Components/…)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-04
  • 1970-01-01
  • 2016-11-19
  • 2011-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多