我开始使用自定义元素,而我不知道的一件事就是共享样式。例如,如果我有2个自定义元素<element-1>
和<element-2>
,它们都包含<button>
,并且我希望所有按钮都具有某种样式,例如font-size:20px
。
我考虑的选项是:
在自定义元素中使用<stylized-button>
自定义元素而不是<button>
。在外部采购<element-1>
时,这是有问题的。如果您还希望仅在color:red
按钮上而不是<element-1>
按钮上进行其他样式设置(例如<element-2>
),也会引起问题。
据我从Polymer的文档[1]得知,聚合物对此也没有解决方案。
/dead/
和:shadow
似乎很有希望,但不再受支持。
类似@apply
[2]似乎很有希望,但是该提案被撤回了。
::part
和::theme
[3]似乎更有希望,但尚未得到支持。
使用js支持::part
和::theme
[4]。我想如果不解决所有问题,这将非常脆弱。
将共享样式明确添加到每个自定义元素。
class Element1 extends HTMLElement {
constructor() {
this.shadowRoot.addElement(sharedStyle);
}
}
这似乎是非常严格的&手动的。还可能会影响性能吗?如果您从外部采购<element-1>
,也会引起问题。
现在,我认为#5可能是最好的,因为它似乎是最通用/最容易使用的,而无需专门为其构建,此外,它在实施时过渡到#4的过程很简单。 但是我想知道是否还有其他方法或建议?
[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
实现:
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>
答案 0 :(得分:1)
您可以使用@import url
将外部样式表导入到不同的自定义元素中。
或者,现在您还可以在自定义元素Shadow DOM中使用<link rel="stylesheet">
:
<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>
答案 1 :(得分:0)
如果您使用的是CSS,则可以执行以下操作:
button {
/* Put Style Here */
}
您还必须在html的头部添加一个链接:
<link rel=“stylesheet” href=“the address”>