与自定义HTML元素共享样式吗? [英] Shared styling with custom HTML elements?

查看:45
本文介绍了与自定义HTML元素共享样式吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始使用自定义元素,而我不知道的一件事就是共享样式.例如,如果我有2个自定义元素,分别是< element-1> < element-2> ,它们都包含< button> 's,我希望所有按钮都具有某种样式,例如 font-size:20px .

I'm beginning to use custom elements, and one thing I can't figure out is sharing styling. For example, if I have 2 custom elements, <element-1> and <element-2>, both of which contain <button>'s, and i want all buttons to have a certain styling, e.g. font-size:20px.

我考虑的选项是:

  1. 在自定义元素中使用< stylized-button> 自定义元素,而不是< button> .当从外部采购< element-1> 时,这是有问题的.如果您还希望仅在< element-1> 按钮而不是< element-2> 按钮.

  1. Use a <stylized-button> custom element instead of <button> in the custom elements. This is problematic when externally sourcing <element-1>. Also problematic if you want other styling as well (e.g. color:red) on only <element-1> buttons and not <element-2> buttons.

据我从Polymer的文档[1]得知,聚合物也没有解决方案.

As far as I could tell from polymer's docs [1], polymer doesn't have a solution for this either.

/dead/:shadow 似乎很有希望,但不再受支持.

/dead/ and :shadow seemed promising but are no longer supported.

类似地 @apply [2]看起来很有希望,但是该提案被撤回了.

Similarly @apply [2] seemed promising, but the proposal was withdrawn.

:: part :: theme [3]似乎更有希望,但尚不支持.

::part and ::theme [3] seem even more promising, but aren't yet supported.

使用js支持 :: part :: theme [4].我想如果不解决所有问题,这将非常脆弱.

Use js to support ::part and ::theme [4]. i imagine this would be very brittle without ironing out all cases.

将共享样式明确添加到每个自定义元素.

Explicitly add the shared styling to each custom element.

class Element1 extends HTMLElement {
    constructor() {
        this.shadowRoot.addElement(sharedStyle);
    }
}

这似乎很受限制&手动的.还可能会影响性能吗?如果您从外部采购< element-1> .

This seems very restricted & manual. Also might affect performance? Also problematic if you externally sourcing <element-1>.

现在,我认为#5可能是最好的,因为它似乎是最通用/最容易使用的,而无需专门为其构建,另外,在实现时,向#4的过渡也将变得微不足道.但是我想知道是否还有其他方法或建议?

Right now, I'm thinking #5 might be the best as it seems the most generic / easiest to use without building specifically for it, plus it would make transitioning to #4 trivial when it's implemented. But I'm wondering if there are other approaches or suggestions?

[1] https://www.polymer-project.org/3.0/docs/devguide/style-shadow-dom

[2] http://tabatkins.github.io/specs/css-apply-rule/

[3] https://meowni.ca/posts/part-theme-explainer/

[4]天真的实现和使用它的示例: https://gist.github.com/mahhov/cbb27fcdde4ad45715d2df3b3ce7be40

[4] A naive implementation and an example using it: https://gist.github.com/mahhov/cbb27fcdde4ad45715d2df3b3ce7be40

实现:

document.addEventListener('DOMContentLoaded', () => {
    // create style sheets for each shadow root to which we will later add rules
    let shadowRootsStyleSheets = [...document.querySelectorAll('*')]
        .filter(element => element.shadowRoot)
        .map(element => element.shadowRoot)
        .map(shadowRoot => {
          shadowRoot.appendChild(document.createElement('style'));
          return shadowRoot.styleSheets[0];
        });

    // iterate all style rules in the document searching for `.theme` and `.part` in the selectors.
    [...document.styleSheets]
        .flatMap(styleSheet => [...styleSheet.rules])
        .forEach(rule => {
          let styleText = rule.cssText.match(/\{(.*)\}/)[1];

          let match;
          if (match = rule.selectorText.match(/\.theme\b(.*)/))
            shadowRootsStyleSheets.forEach(styleSheet => styleSheet.addRule(match[1], styleText));
          else if (match = rule.selectorText.match(/\.part\b(.*)/))
            shadowRootsStyleSheets.forEach(styleSheet => styleSheet.addRule(`[part=${match[1]}]`, styleText));
        });
  });

及其用法:

<style>
  .my-element.part line-green {
    border: 1px solid green;
    color: green;
  }

  .theme .line-orange {
    border: 1px solid orange;
    color: orange;
  }

  /*
    must use `.part` instead of `::part`, and `.theme` instead of `::theme`
    as the browser prunes out invalid css rules form the `StyleSheetList`'s. 
  */
</style>

<template id="my-template">
  <p part="line-green">green</p>
  <p class="line-orange">orange</p>
</template>

<my-element></my-element>

<script>
  customElements.define('my-element', class extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({mode: 'open'});
      const template = document.getElementById('my-template').content.cloneNode(true);
      this.shadowRoot.appendChild(template);
    }
  });
</script>

推荐答案

您可以使用 @import url 将外部样式表导入到不同的自定义元素中.

You can use @import url to import an external stylesheet into different custom elements.

或者,现在您也可以在自定义元素Shadow DOM中使用< link rel ="stylesheet">

Alternately now you can also use <link rel="stylesheet"> inside a custom element Shadow DOM:

<template id="element-1">
  <style> 
      @import url( 'button-style.css' )
  </style>
  <button>B-1</button>
</template>

<template id="element-2">
  <link rel="stylesheet" href="button-style.css">
  <button>B-2</button>
</template>

这篇关于与自定义HTML元素共享样式吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆