var styletag = document.createElement("style");
document.head.appendChild(styletag);
styletag.appendChild(document.createTextNode('')); // This is needed to replicate issue
styletag.sheet.insertRule("#inner { background-color: red;} ");
setTimeout(()=>styletag.textContent='',1000)
<span id="inner">content</span>
这段特定的代码为
#inner
元素添加了适当的样式。直到 setTimeout
代码运行并且 textContent
重置为空字符串。styletag.sheet.cssRules
) 变为空,并且 background-color
被删除。var styletag = document.createElement("style");
document.head.appendChild(styletag);
// styletag.appendChild(document.createTextNode('')); // This is needed to replicate issue
styletag.sheet.insertRule("#inner { background-color: red;} ");
setTimeout(()=>styletag.textContent='',1000)
<span id="inner">content</span>
如果我使用类似的东西我就可以理解
styletag.textContent = "#inner { background-color: red;} "
而不是
styletag.sheet.insertRule("#inner { background-color: red;} ");
这里将
textContent
重置为空会删除规则,这是有道理的。textContent
会让浏览器重新评估 CSSRules
?但如果是这样,为什么只有当我将空文本节点附加到 <style>
标签时才能复制该问题?
这非常复杂,说实话也很令人惊讶,但问题的要点是,
<style>
元素将在 3 种情况下根据其内容更新其规则:
在我们的例子中,第一个并不重要,因为我们是动态创建元素而不是从解析器创建元素。
第二个的重要性也很有限,当我们将元素追加到 DOM 中时就会发生这种情况,但我们并不真正关心它之前是什么。唯一的问题是,当在 DOM 中时,我们有第一个
sheet
,它是根据当前(空)内容计算出来的。
然后我们就改变了元素的子元素。当节点被“插入”时(第 9 步),就会调用该算法。因此,当您附加空的 TextNode
时,将运行此步骤,并且
<style>
将再次更新其规则,但没有内容……更新也不是很重要。但重要的是,现在我们的 <style>
确实有一个子节点。 事实上,当使用空字符串运行
textContent
setter 步骤时,目标元素的前一个子元素会被删除,并且不会添加新节点,但 insert 步骤仍然会运行。 但是,当目标元素中没有先前的子元素时,不会删除任何节点,也不会添加新节点。 插入步骤未运行,并且我们从未达到孩子更改了步骤。 所以这一切都归结为当有或没有以前的内容时
textContent = ""
如何不同地运行。