我在将我的 webcomponent 实例的采用样式表添加到文档中时遇到问题。
我的自定义 web 组件在构造函数中创建了一个新的 CSSStyleSheet 实例。当组件被 connectedCallback 升级时,它会将实例添加到 document.adoptedStyleSheets 中。然后我有一个 update() 方法,稍后可以调用它来更改所采用样式表的 css 属性。
在以下示例中,您可以看到用法。我的 HTML 包含两个自定义组件和一些用于添加和删除样式属性的按钮。
我们可以使用添加按钮为这两个组件添加不同的样式。一切正常,直到开发人员属性未打开。如果您打开开发人员属性并重新加载示例,似乎添加到采用的样式表的两个 CSSStyleSheet 实例都引用了同一个实例。
单击元素 1 旁边的“应用样式”按钮将为元素 1 添加一个绿色边框。
单击元素 2 旁边的“应用样式”按钮将为元素 2 添加黑色边框。
但它删除了元素 1 的样式。这不应该发生,因为元素 1 的 CSSStyleSheet 对象仍然应该具有自己的 css 属性。但他们迷路了。
class CustomElem extends HTMLElement {
constructor() {
super();
this.myStyle = new CSSStyleSheet();
}
connectedCallback() {
document.adoptedStyleSheets = [ ...document.adoptedStyleSheets, this.myStyle ];
}
update(css) {
this.myStyle.replaceSync(css);
}
}
customElements.define('custom-elem', CustomElem);
document.getElementById('btn1_add').addEventListener('click', function() {
document.getElementById('elem1').update('custom-elem#elem1 { border: 3px solid green; }');
});
document.getElementById('btn2_add').addEventListener('click', function() {
document.getElementById('elem2').update('custom-elem#elem2 { border: 3px solid black; }')
});
document.getElementById('btn1_remove').addEventListener('click', function() {
document.getElementById('elem1').update('');
});
document.getElementById('btn2_remove').addEventListener('click', function() {
document.getElementById('elem2').update('')
});
<html>
<head></head>
<body>
Custom Elements<br /><br/>
<custom-elem id="elem1">Element 1</custom-elem>
<input type="button" id="btn1_add" value="Apply Style"></input>
<input type="button" id="btn1_remove" value="Remove Style"></input>
<br /><br />
<custom-elem id="elem2">Element 2</custom-elem>
<input type="button" id="btn2_add" value="Apply Style"></input>
<input type="button" id="btn2_remove" value="Remove Style"></input>
</body>
</html>
我的第二个示例解决了这个问题。如果我直接在 connectedCallback 中调用 replaceSync(''),everythink 会像预期的那样工作。
class CustomElem extends HTMLElement {
constructor() {
super();
this.myStyle = new CSSStyleSheet();
}
connectedCallback() {
document.adoptedStyleSheets = [ ...document.adoptedStyleSheets, this.myStyle ];
// *****************************
// this makes it work!
// *****************************
this.myStyle.replaceSync('');
}
update(css) {
this.myStyle.replaceSync(css);
}
}
customElements.define('custom-elem', CustomElem);
document.getElementById('btn1_add').addEventListener('click', function() {
document.getElementById('elem1').update('custom-elem#elem1 { border: 3px solid green; }');
});
document.getElementById('btn2_add').addEventListener('click', function() {
document.getElementById('elem2').update('custom-elem#elem2 { border: 3px solid black; }')
});
document.getElementById('btn1_remove').addEventListener('click', function() {
document.getElementById('elem1').update('');
});
document.getElementById('btn2_remove').addEventListener('click', function() {
document.getElementById('elem2').update('')
});
<html>
<head></head>
<body>
Custom Elements<br /><br/>
<custom-elem id="elem1">Element 1</custom-elem>
<input type="button" id="btn1_add" value="Apply Style"></input>
<input type="button" id="btn1_remove" value="Remove Style"></input>
<br /><br />
<custom-elem id="elem2">Element 2</custom-elem>
<input type="button" id="btn2_add" value="Apply Style"></input>
<input type="button" id="btn2_remove" value="Remove Style"></input>
</body>
</html>
谁能告诉我,为什么会这样?