Web Components 中的路径是相对于 Root 的

Paths in Web Components are Relative to Root

我正在使用本机实现创建一个 Web 组件,它的 html 模板中有指向图像的链接。 但是,这些链接只有在绝对链接或相对于主文档的情况下才有效,这意味着该组件不可重用或不可移植。而且,这是非常违反直觉的。

目前,我为所有需要使用图像的元素添加了一个data-url_prefix属性。然后,在为我的自定义元素创建影子根时,我将 {{URL_PREFIX}} 替换为该参数的值。

我的解决方案似乎很糟糕。如果您有更好的建议,我将非常高兴,谢谢。


我在 http://webcomponents.org/polyfills/html-imports/ 页面上发现了一个有趣的引用:

POLYFILL NOTES

In imported documents, href and src attributes in HTML, and url properties in CSS files, are relative to the location of the imported document, not the main document.

为什么 polifill 使用与本机实现不同的逻辑?


Web 组件理想情况下应该封装它们的所有依赖项,但如果 Web 组件需要图像,它应该知道该图像的绝对 URL,这不允许组件在文件中简单地移动结构。

比如说,我有以下结构:

如果我将其更改为以下内容:

我需要将指针更改为指向这些文件中某处的 icon.png 我的问题是如何避免它,或者以优雅的方式解决它。另外,为什么实际的原生实现与 polyfill 冲突?

这种行为似乎是图片特有的。
对于脚本和 link 标签,导入文档的相对路径按预期工作。

我还注意到这不是 polyfill 特有的东西,即使是本机实现(chrome)这个问题(?)似乎也存在。

似乎这里唯一的选择是在导入的 html 中包含一个脚本,这会将这些相对路径转换为它们的绝对对应路径。
要优雅地解决它,您可以避免在脚本中对 url 进行硬编码,并使用导入文档的 url 生成它。您可以从 document.currentScript.ownerDocument(或 polyfilled 场景中的 document._currentScript.ownerDocument)获得。

因此,为了回答您的第二个问题,我认为至少在 srchref 属性的行为方面,本机和 polyfilled 实现没有任何区别。
您在 http://webcomponents.org/polyfills/html-imports/ 中提到的引述似乎特定于 href/src 的脚本和 link 标签,它们按书面方式工作。

希望对您有所帮助。

webcomponent 规范定义 URLs 总是相对于主文档。正如您正确地得出结论,这当然会破坏 Web 组件封装。换句话说,这个规范是有问题的,很多人都在抱怨它。这就是 polyfill 不遵循规范的原因:它正在解决问题。

规格将会改变。但是,由于修复起来并非易事,因此仍需要一些时间。请查看这些链接:

https://lists.w3.org/Archives/Public/public-webapps/2014OctDec/0013.html

https://www.w3.org/Bugs/Public/show_bug.cgi?id=20976#c8

目前,解决方案是让您的组件将其模板图像的 URL 从相对更改为绝对。您可以通过以下方式获得 templateBaseUrl

(function (window, document)
    {
    var proto = Object.create(HTMLElement.prototype);

    var template = document.currentScript.ownerDocument.querySelector("template");
    var templateBaseUrl = template.baseURI;

    proto.createdCallback = function ()
        {
        // Now find all images inside the template and change their src attribute, 
        // using templateBaseUrl. Also you must change CSS background-image: url(...);
        ...
        };

    document.registerElement('test-element', {prototype: proto});
    })(window, document);

对于像图标这样的小图像,解决此问题的另一种方法是使用 数据 URI 将图像数据直接嵌入到文档中。这也节省了 HTTP 请求(直到我们有 Http/2)。例如:

<img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" />

根据我自己对 MarcG 回答的上一条评论做出反应 - 模块了解其自身路径的需求已得到认可,现在可以通过 import.meta.url 平均检索!

所以现在编写一些 util 来获取组件的 HTML/CSS。

此外,如果未获取 CSS,而是将新样式 sheet link 动态添加到文档中 - 此 CSS 与相对路径配合得非常好.

今天,在等待一些标准方法来指定我的组件的基础时 url,我现在的方法是为组件提供 2 种资源:

  • main/single HTML 通过 fetch API 获取,转换为模板,缓存,然后每次将其新实例附加到 DOM
  • main CSS 由标准 link 元素link编辑
  • 这 2 个的名称与提供组件 class 的主要 JS 文件相同 - 使将整个混乱变成一打代码更容易
  • 其他 CSS 资源,如果需要,添加为主要的常规相对导入 CSS
  • 图像,如果可能,也使用相对导入作为 url 背景添加
  • 显然不超过单个 HTML 资源