问题描述
我在将WebComponent实例的过继样式表添加到文档中时遇到问题。
我的自定义Web组件在构造函数中创建了一个新的CSsstyleSheet实例。当组件通过connectedCallback升级时,它将实例添加到document.adoptedStyleSheets中。 然后,我有一个update()-Method,以后可以调用它来更改所采用样式表的css属性。
在以下示例中,您可以查看用法。我的HTML包含两个自定义组件以及一些用于添加和删除样式属性的按钮。
我们可以通过使用添加按钮向两个组件添加不同的样式。在未打开开发人员属性之前,一切工作正常。 如果打开开发人员属性并重新加载该示例,则似乎添加到采用的StyleSheets中的两个CSsstyleSheet实例都引用同一实例。
单击元素1旁边的“应用样式”按钮将为元素1添加绿色边框。
单击元素2旁边的“应用样式”按钮,将在元素2上添加黑色边框。
但是它删除了Element 1的样式。这不会发生,因为Element 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(''),那么一切都会按预期进行。
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',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>
有人可以告诉我,为什么会这样吗?
解决方法
根据issue you've reported on bugs.chromium.org,这实际上是Chrome回归,引入了与Chrome 85中的样式表突变相关的更改。它在85年前已经正常工作。
顺便说一句,非常好的复制者!
fix has already been implemented和可以使用Chrome Canary进行验证。该修补程序将在Chrome 88中登陆,该Chrome 88将于2021年1月19日成为稳定版本(请参见releases)。