【问题标题】:webcomponents.js Shadow DOM :host selector does not work on Safari and Firefoxwebcomponents.js Shadow DOM:主机选择器在 Safari 和 Firefox 上不起作用
【发布时间】:2015-06-02 14:57:37
【问题描述】:

我尝试使用来自 https://github.com/webcomponents/webcomponentsjs 的 polyfill 制作自己的 Web 组件

这是我的代码:

im-list.html

<template id="im-list-temp">
  <style>
    :host {
      list-style-type: none;
      margin: 0;
      padding: 0;
    }
  </style>
  <content> </content>
</template>

<script>
  var currentScript = document._currentScript || document.currentScript;
  var proto = Object.create(HTMLUListElement.prototype, {
    createdCallback: {
      value: function() {
        var doc = currentScript.ownerDocument;
        var t = doc.querySelector("#im-list-temp");
        var clone = doc.importNode(t.content, true);
        var root = this.createShadowRoot();
        root.appendChild(clone);
      }
    }
  });
  document.registerElement('im-list', {
    prototype: proto,
    extends: 'ul'
  });
</script>

index.html

<!DOCTYPE html>
<html>
  <head>
    <script src="bower_components/webcomponentsjs/webcomponents.js"></script>
    <link rel="import" href="./components/im-list.html" />
    <title>List Test</title>
  </head>
  <body>
    <ul is="im-list">
      <li>Blubb</li>
      <li>Blubb Blubb</li>
    </ul>
  </body>
</html>

此代码在 Chrome (43.0.2357.81) 中运行良好,但在 Firefox(38.0.1 和 40.0a2)和 Safari(8.0.6)中无法运行。在 FF 和 Safari 中,&lt;style&gt; 只是添加到普通 DOM 中。

【问题讨论】:

    标签: javascript html css web-component shadow-dom


    【解决方案1】:

    GitHub Repository

    我把这个和其他sn-ps放在github上。随意分叉和改进。


    问题在于 webcomponets.js 没有“修复”在缺乏原生 ShadowDOM 支持的浏览器上使用的样式。也就是说,它不会使浏览器能够理解像:host 这样的选择器。

    Polymer 解决它的方法,is by rewriting the style

    所以,在 Polymer 下,这个:

    :host ::content div
    

    变成这样:

    x-foo div
    

    因此,要在 VanillaJS 组件下拥有它,必须手动执行此操作。

    这是我用来创建 Shadow Root 并仅在使用 webcomponents.js 而不是原生 Shadow DOM 的浏览器上重写样式的 sn-p:

    var addShadowRoot = (function () {
      'use strict';
      var importDoc, shimStyle;
    
      importDoc = (document._currentScript || document.currentScript).ownerDocument;
    
      if (window.ShadowDOMPolyfill) {
        shimStyle = document.createElement('style');
        document.head.insertBefore(shimStyle, document.head.firstChild);
      }
    
      return function (obj, idTemplate, tagName) {
        var template, list;
    
        obj.root = obj.createShadowRoot();
        template = importDoc.getElementById(idTemplate);
        obj.root.appendChild(template.content.cloneNode(true));
    
        if (window.ShadowDOMPolyfill) {
          list = obj.root.getElementsByTagName('style');
          Array.prototype.forEach.call(list, function (style) {
            if (!template.shimmed) {
              shimStyle.innerHTML += style.innerHTML
                .replace(/:host\b/gm, tagName || idTemplate)
                .replace(/::shadow\b/gm, ' ')
                .replace(/::content\b/gm, ' ');
            }
            style.parentNode.removeChild(style);
          });
          template.shimmed = true;
        }
      };
    }());
    

    复制粘贴到你的组件上。

    接下来,您需要在 createdCallback 中调用此函数,例如:

    addShadowRoot(this, "im-list-temp", "ul[is=im-list]");
    

    Here is an example with your code

    【讨论】:

    • 这行得通,所以我接受了答案,但我最终得到的解决方案是改用聚合物。
    猜你喜欢
    • 2015-07-24
    • 1970-01-01
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多