16

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

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

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


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

填充注意事项

在导入的文档中,HTML 中的 href 和 src 属性以及 CSS 文件中的 url 属性是相对于导入文档的位置,而不是主文档。

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


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

比如说,我有以下结构:

  • 索引.html
  • css
    • main.css
  • js
    • main.js
  • web_components
    • cool_web_component
      • cool_web_component.html
      • 图标.png

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

  • 索引.html
  • css
    • main.css
  • js
    • main.js
  • cool_web_component
    • cool_web_component.html
    • 图标.png

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

4

3 回答 3

14

webcomponent 规范定义 URL 总是相对于主文档。正如您正确得出的结论,这当然会破坏 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);

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

<img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" />
于 2015-11-09T06:07:39.767 回答
1

这种行为似乎特定于图像。
对于脚本和链接标签,来自导入文档的相对路径按预期工作。

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

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

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

希望能帮助到你。

于 2015-11-05T13:39:59.283 回答
0

对我自己对 MarcG 答案的上一个评论做出反应 - 模块需要知道自己的路径已经得到承认,现在可能会被import.meta.url平均检索!

因此,现在编写一些工具来获取组件的 HTML/CSS 要容易得多。

此外,如果未获取 CSS,而是将新样式表链接动态添加到文档中 - 此 CSS 还可以很好地与相对路径配合使用。

有了它,今天,在等待某种标准方法来指定我的组件的基本 url 时,我的方法是为组件提供 2 个资源:

  • 主/单个 HTML 通过fetchAPI 获取,转换为模板,缓存,然后每次将新实例附加到 DOM 时克隆到组件中
  • 主 CSS 由标准link元素链接
  • 这两个的名称与提供组件类的主 JS 文件相同 - 使得将整个混乱变成十几行实用程序变得更容易
  • 额外的 CSS 资源,如果需要,作为常规的相对导入添加到主 CSS 中
  • 如果可能,图像也可以使用相对导入添加为 url 背景
  • 显然不超过单一的 HTML 资源
于 2018-12-20T22:55:23.997 回答