Web组件中的路径相对于根

时间:2015-10-31 18:10:42

标签: javascript html polymer web-component custom-element

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

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

我的解决方案似乎很糟糕。如果你建议更好的话,我会很高兴,谢谢。

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

  

POLYFILL NOTES

     

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

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

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

比如说,我有以下结构:

  • 的index.html
  • CSS
    • 的main.css
  • JS
    • main.js
  • web_components
    • cool_web_component
      • cool_web_component.html
      • 的icon.png

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

  • 的index.html
  • CSS
    • 的main.css
  • JS
    • main.js
  • cool_web_component
    • cool_web_component.html
    • 的icon.png

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

3 个答案:

答案 0 :(得分:6)

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);

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

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

答案 1 :(得分:1)

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

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

这里似乎唯一的选择是在导入的html中包含一个脚本,它会将这些相对路径转换为绝对路径。
为了优雅地解决它,您可以避免在脚本中硬编码网址并使用导入文档的网址生成网址。您可以从document.currentScript.ownerDocument(或填充方案中的document._currentScript.ownerDocument)获取该内容。

因此,为了回答您的第二个问题,至少在srchref属性的行为方面,我发现原生和多种填充实施方式没有任何差异。
你在http://webcomponents.org/polyfills/html-imports/中提到的引用似乎特定于脚本和链接标记的href / src,它们的工作方式也是如此。

希望它有所帮助。

答案 2 :(得分:0)

根据我对MarcG答案的先前评论-认识到模块知道自己的路径的必要性,如今,import.meta.url的意思可能可以找回模块!

因此,现在编写一些实用程序来获取组件的HTML / CSS变得容易得多。

此外,如果未获取CSS,而是向文档动态添加了一个新的样式表链接,则此CSS在相对路径上的表现也很好。

今天,在等待某种标准方法指定组件的基本URL的同时,我的ow方法是为组件提供2种资源:

  • 通过fetch API提取主要/单个HTML,将其转换为模板,进行缓存,然后在每次将新实例附加到DOM时将其克隆到组件中
  • 主要CSS通过标准link元素
  • 链接 这2个
  • 的名称与提供组件的主JS文件的名称相同-使将整个混乱变成十几行实用程序
  • 更容易
  • 必要时将其他CSS资源作为常规相对导入添加到主CSS中
  • 图像(如果可能)也使用相对导入作为网址背景添加
  • 只不过是混淆HTML资源而已