将window.document样式应用于Polymer 2子元素

时间:2017-07-14 12:54:51

标签: javascript css dom polymer polymer-2.x

我正在开发一个应用程序,用户可以通过拖放来构建网页。我们的用户可以删除的一些元素是Polymer2元素。

用户还可以在页面中添加自定义样式表,如果他们这样做,那里定义的样式应该会影响Polymer2元素的子项。

现在,我知道所有这些都违背了网络组件的行为方式,但我仍然想知道它是否可行。

我是Polymer的新手,并不太确定在哪个方向上看。我读过关于mixins,共享样式和自定义样式的内容,但似乎没有一个为我的用例提供有效的方法。

非常感谢任何帮助。

修改

到目前为止,我发现有一种解决方案可以正常运行但不理想,因为将来会弃用import

/parent-styles.html

<link rel="import" href="../../bower_components/polymer/polymer.html">
<dom-module id="parent-styles">
    <link rel="import" type="css" href="ref_to_page_stylesheet.min.css">
</dom-module>

然后我可以导入此文件并使用<style include="parent-styles"></style>。这至少允许从页面的样式表中设置Polymer元素的样式,但显然这个解决方案会在样式表名称或位置发生变化时立即中断,我对此并不满意。

2 个答案:

答案 0 :(得分:1)

  

为Web组件设置样式有很多选项。一个组件   使用shadow DOM可以通过主页面设置样式,定义自己的样式,   或者为用户提供钩子(以CSS自定义属性的形式)   覆盖默认值。

要从外部设置组件<fancy-tabs>的样式,您只需将其标记名称用作选择器:

fancy-tabs {
  width: 350px;
}

外部样式总是胜过shadow DOM中定义的样式。但这只能让你到目前为止。如果你想为<fancy-tabs>的内部设计样式怎么办?这是您必须使用自定义CSS属性创建样式挂钩的地方。

示例:

<!-- main page -->
<style>
  fancy-tabs {
    margin-bottom: 32px;
    --fancy-tabs-bg: black;
  }
</style>
<fancy-tabs background>...</fancy-tabs>

<fancy-tabs>的影子DOM中:

:host([background]) {
  background: var(--fancy-tabs-bg, #9E9E9E);
  border-radius: 10px;
  padding: 10px;
}

在这种情况下,组件将使用黑色作为背景值,因为用户提供了它。否则,它将默认为#9E9E9E

使用的参考:Shadow DOM v1: Self-Contained Web Components

答案 1 :(得分:0)

我自己制定了一些解决方案。正如我在问题中已经说过的那样,它有点违背了封装的Web组件哲学。它还依赖于将来会被弃用的链接标记。最糟糕的是,我还没有进行任何跨浏览器测试......所以:

小心使用!

您可以像下面这样使用下面的样式模块(导入后):

<style include="bb-shared-styles"></style>

<dom-module id="bb-shared-styles">
  <template id="style-template">
    <style id="stylesheet"></style>
  </template>

  <script>
    ((document) => {
      const doc        = (document._currentScript || document.currentScript).ownerDocument;
      const domModule  = doc.querySelector('#bb-shared-styles');
      const template   = doc.querySelector('#style-template');
      const pageStyles = document.styleSheets;
      const styles     = template.content.querySelector('#stylesheet');
      styles.type      = 'text/css';

      
      processStyleSheets();

      function processStyleSheets () {
        for (let index = 0; index < document.styleSheets.length; index++) {
          const sheet = document.styleSheets[index];
          if (sheet.href) {
            // Prefer adding links to parsing CSS rules for better performance
            appendLink(sheet.href);
          } else {
            const rules = sheet.rules || sheet.cssRules;
            if (rules) {
              // For inline styles
              appendRules(rules);
            }
          }
        }
      }

      function appendRules (rules) {
        const len = rules.length;
        for (let index = 0; index < len; index++) {
          const rule = rules[index];
          styles.appendChild(document.createTextNode(rule.cssText));
        }
      }

      function appendLink (href) {
        let link   = document.createElement('link');
        link.rel   = 'import';
        link.type  = 'css';
        link.href  = href;
        domModule.insertBefore(link, domModule.firstChild);
      }

    })(document);
  </script>
</dom-module>