【发布时间】:2020-01-16 06:49:33
【问题描述】:
我最近开始接触 WebComponents,我必须说到目前为止我发现它具有开创性!为了更好地理解这个概念,我尝试将我早期项目中的设计融入可重用的 Web 组件中。我首先尝试创建一个带有一些附加功能的 Table 元素。
首先,我为组件声明了一个最小模板:
<template id="data-table-template">
<table>
<thead></thead>
<tbody></tbody>
<tfoot></tfoot>
</table>
</template>
我使用此模板通过将表头值和行值作为属性来创建表。该元素的使用方式如下:
<eur-data-table
headers="getHeaders()",
rowdata="getRowData()"
host="#data-table-host"
template="#data-table-template"
></eur-data-table>
在组件原型connectedCallback 方法中,我为组件添加标题、行和设置样式。 Chrome Element 检查器生成的 shadow DOM 片段如下:
<eur-data-table headers="getHeaders()" ,="" rowdata="getRowData()" host="#data-table-host" template="#data-table-template" theme="firebrick">
<table>
<style id="styleBlock"></style>
<thead>
<th>Name</th>
<th>Age</th>
</thead>
<tbody>
<tr>
<td>Babu</td>
<td>60</td>
</tr>
<tr>
<td>Shyam</td>
<td>35</td>
</tr>
</tbody>
<tfoot></tfoot>
</table>
</eur-data-table>
问题在于添加样式规则。在组件类中,我创建了一个 style 元素并将其附加到影子 DOM,然后再将规则添加到 style.sheet 属性。我检查了style.sheet 的控制台输出,看起来所有规则都已添加。但是,在将样式元素插入到 shadow DOM 之后,从上面渲染的输出中可以看出没有任何规则。
在组件类中,样式的添加方式如下:
connectedCallback() {
let template = document.querySelector(DataTable._parseId(this.template));
if(!template) throw new DOMException('Host and/or template ids are undefined');
if(!this.hasAttribute('theme')) this.setAttribute('theme', 'firebrick');
let style = document.createElement('style');
style.setAttribute('id', 'styleBlock');
// WebKit Hack
style.appendChild(document.createTextNode(""));
this.shadowRoot.appendChild(style);
this._table = template.content.cloneNode(true);
this._setupHeaders();
this._setupBody();
this._setupStyle(style.sheet); // style is not being applied!!
console.dir(style.sheet); // logs a CSSStyleSheet object
this.shadowRoot.appendChild(this._table);
}
在connectedCallback方法中,_setupStyle被传递一个对样式表的引用,它以如下方式添加规则(规则表示为javascript对象):
_setupStyle(sheet) {
if(!sheet) throw new DOMException('sheet is undefined', 'StylesheetNotFoundException');
let rules = window.themes[this.theme];
if(!rules) throw new DOMException('Theme is undefined');
Object.keys(rules)
.sort((r1, r2) => rules[r1].order - rules[r2].order)
.forEach(rule => {
let o = _.omit(rules[rule], 'order');
let i = rule.order;
let s = this._makeRule(o, rule);
sheet.insertRule(s, i);
});
}
order 值是一个整数,用于按顺序对样式规则进行排序。排序后,order 键及其值在将其转换为 DOMString 之前从对象中省略:
_makeRule(value, rule) {
return `${rule} ${JSON.stringify(value).replace(new RegExp(/,/g), ';')}`;
}
记录style.sheet 属性打印:
CSSStyleSheet
cssRules: CSSRuleList
0: CSSStyleRule {selectorText: "tfoot", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "tfoot { }", …}
1: CSSStyleRule {selectorText: "tr:last-child > td", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "tr:last-child > td { }", …}
2: CSSStyleRule {selectorText: "td:last-child", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "td:last-child { }", …}
3: CSSStyleRule {selectorText: "td", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "td { }", …}
4: CSSStyleRule {selectorText: "tr:first-child", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "tr:first-child { }", …}
5: CSSStyleRule {selectorText: "tr:last-child", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "tr:last-child { }", …}
6: CSSStyleRule {selectorText: "tr", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "tr { }", …}
7: CSSStyleRule {selectorText: "th:last-child", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "th:last-child { }", …}
8: CSSStyleRule {selectorText: "th", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "th { }", …}
9: CSSStyleRule {selectorText: "thead", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "thead { }", …}
10: CSSStyleRule {selectorText: "thead tbody tfoot", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "thead tbody tfoot { }", …}
11: CSSStyleRule {selectorText: "table", style: CSSStyleDeclaration, styleMap: StylePropertyMap, type: 1, cssText: "table { }", …}
我的问题是:由于组件渲染时没有错误,而且我按预期添加所有规则并将样式和表格元素附加到影子 DOM 中,然后按预期呈现元素,为什么不是我的CSS 规则被应用于渲染的内容?
【问题讨论】:
标签: css web-component shadow-dom