为什么使用 insertRule 在空样式标签中插入的规则会在重置 textContent 时被删除?

问题描述 投票:0回答:1

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>
标签时才能复制该问题?

javascript html css dom emotion
1个回答
0
投票

这非常复杂,说实话也很令人惊讶,但问题的要点是,

<style>
元素将在 3 种情况下根据其内容更新其规则

  • 该元素从 HTML 解析器或 XML 解析器的打开元素堆栈中弹出。

  • 该元素不在 HTML 解析器或 XML 解析器的打开元素堆栈上,并且它变为已连接或已断开连接。

  • 元素的子级更改了步骤运行。

在我们的例子中,第一个并不重要,因为我们是动态创建元素而不是从解析器创建元素。

第二个的重要性也很有限,当我们将元素追加到 DOM 中时就会发生这种情况,但我们并不真正关心它之前是什么。唯一的问题是,当在 DOM 中时,我们有第一个

sheet
,它是根据当前(空)内容计算出来的。

然后我们就改变了元素的子元素。当节点被“插入”时(第 9 步),就会调用该算法。因此,当您附加空的 TextNode 时,将运行此步骤,并且

<style>
将再次更新其规则,但没有内容……更新也不是很重要。但重要的是,现在我们的
<style>
确实
有一个子节点。 事实上,当使用空字符串运行
textContent setter 步骤
 时,目标元素 
的前一个子元素会被删除
,并且不会添加新节点,但 insert 步骤仍然会运行。 但是,当目标元素中没有先前的子元素时,不会删除任何节点,也不会添加新节点。 插入步骤未运行,并且我们从未达到孩子更改了步骤 所以这一切都归结为当有或没有以前的内容时

textContent = ""

如何不同地运行。

    

© www.soinside.com 2019 - 2024. All rights reserved.