正文共:1892 字
预计阅读时间:10 分钟
作者:Scott Jehl
翻译:疯狂的技术宅
来源:filamentgroup
注意:这篇文章描述了一种我们仍需要测其试性能影响的实验技术。它可能最终会成为一种有用的工具,也有可能成为不被推荐的做法。无论哪种方式,它对我们来说很有吸引力!
只要我一直工作在 Web 上,就需要一种简单的 HTML 驱动方式,将另一个文件的内容直接包含在页面中。例如,我经常希望向页面添加额外的 HTML,或者嵌入 SVG 文件的内容,以便我们可以为其设置动画和样式。通常我们通过使用 JavaScript 获取文件并将其内容附加到特定元素,或者通过在服务器端去包含文件来实现这种嵌入,但在大多数情况下,这些方法都不是我们想要的。
本周我在思考如何用一些新的与 fetch
相关的标记模式来实现这一点,例如 rel="preload"
或 HTML import,但我总是得出的相同结论,即这些都不能使你方便地访问所取得的文件的内容。然后我想,假设浏览器允许我在父文档中检索 iframe
的内容,也许一个旧的 iframe
可能是一个很不错的模式。事实证明,它肯定会的!
下面是一个内联(嵌入式)SVG 图形。它是从外部文件 signal.svg
中加载的。
要加载并嵌入 SVG 文件,我用了下面的标记:
<iframe src="signal.svg" onload="this.before((this.contentDocument.body || this.contentDocument).children[0]);this.remove()"></iframe>
尽管此标记以 iframe
开头,但如果你使用开发人员工具检查上面的图形,将会看到 SVG 的图标标记,就内嵌在 HTML DOM 中,而且找不到 iframe
元素。这是因为代码用 iframe
加载文件,并且在删除 iframe之前,用 onload
事件在 HTML 中 iframe
的位置之前注入了 iframe
里的内容。
该方法也适用于 object
元素,无论如何它通常用于引用SVG,所以我认为这特别好。对于一个object
,src
属性必须用 data
替代:
<object data="signal.svg" onload="this.before((this.contentDocument.body || this.contentDocument).children[0]);this.remove()"></object>
也许更有用……这是一个使用HTML而不是SVG的例子!
可以用下面的标记加载:
<iframe src="/images/includespost/htmlexample.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"></iframe>
一个说明这一个:你可能已经注意到,标记片段检查 contentDocument.body
或仅检查 contentDocument
。这是对 HTML 和 SVG 包含进行的规范化检查。这是必要的,因为即使 HTML 文件本身只包含一个段落元素,浏览器也会创建一个完整的 HTML 文档来包装该段落,并包含 HTML 元素、head、body等。所以该片段会试图获取 iframe
的 body
元素(如果存在),如果不存在,它将会用于整个文档。
值得注意的是,如果你要导入包含多个元素的 HTML 文件,我建议将其全部包装在 div 中,以使 iframe
标记能够简单地查找 body
中的第一个子节点。
与我们过去使用的其他模式相比,这种模式有一些很明显的好处:
iframe
的性质。iframe
的内容移动到父文档中,即便失败了,你仍会看到包含的内容。iframe
将内容导入页面后会被删除。注意:你可能希望为 iframe
指定 border:0;
甚至可以在加载时安全地隐藏它(或许通过 onerror 事件再次显示它?)。iframe
中的备选内容,但我认为可以通过调整 onload
处理中的 JS 来获得对 IE 的支持,因为它目前用的是 IE 不喜欢的语法。稍微调整一下,我认为 IE 支持是可能的。考虑其他可能的用途很有趣……也许你可以引入 HTML 模块及其相关的 CSS 链接。或者在文档或博客文章中嵌入推文或代码。它甚至可能用于异步加载和应用常规的 rel=stylesheet
链接,并且优先级较低,否则很难做到(注意:我没有对这个想法进行太多的测试)。
使用 iframe
进行此模式的另一个好处是, iframe
会在进入视口时获得延迟加载的能力。这可以用 load ="lazy"
属性来实现,该属性也适用于 img
元素。代码看起来是这样:
<iframe src="signal.svg" loading="lazy" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"></iframe>
iframe
在 web 上很常用,但是在页面中过度使用 iframe 可能会导致性能或内存消耗问题。例如对页面上所有图标使用可能会过重,但是对于需要进行动画和样式化的特定图标来说,它可能会很好用。不过现在我只能做更多的测试。
还有可能存在XSS问题,但我不确定这与其他需要注意外部内容的情况有什么不同。你仍需要做通常的安全检查,并且最好将其看作是同域技术,尽管我也不确定。
就目前而言,这种做法有希望成为之前将另一个文件直接包含在页面中方法的改进。
我们将会继续测试这种模式,如果我们发现了什么有趣的内容,会很快发布后续内容。如果你有什么反馈或想法,请随时在Twitter(https://twitter.com/filamentgroup)上与我们联系。谢谢阅读! 原文:https://www.filamentgroup.com/lab/html-includes/