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

Why rules inserted in an empty style tag using insertRule get removed on resetting textContent?

提问人:Kritidipto Ghosh 提问时间:10/30/2023 最后编辑:KaiidoKritidipto Ghosh 更新时间:10/30/2023 访问量:77

问:

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>

这段特定的代码会向元素添加适当的样式。直到代码运行并重置为空字符串。
然后样式表的规则 () 变为空,并且 被删除。
出于某种原因,需要第三行来复制此问题。
#innersetTimeouttextContentstyletag.sheet.cssRulesbackground-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;} ");

在这里,重置为空将删除规则,这是有道理的。
也许设置使浏览器重新评估?但是,如果是这样,为什么只有当我在标签上附加一个空文本节点时,问题才可复制?
textContenttextContentCSSRules<style>

JavaScript HTML CSS DOM 情感

评论


答:

3赞 Kaiido 10/30/2023 #1

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

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

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

  • 该元素不在 HTML 解析器或 XML 解析器的打开元素堆栈中,并且它将连接或断开连接

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

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

第二个也只是有限的重要性,当我们在 DOM 中附加元素时就会发生,但我们并不真正关心它以前是什么。唯一的问题是,当在 DOM 中,我们有一个从当前(空)内容中计算出来的第一个。sheet

然后我们让元素的子项改变一个。当插入节点(步骤 9)或删除节点(步骤 21)时,将调用此算法。因此,当您附加空时,将运行此步骤,并且将再次更新其规则,没有内容,再次...该更新也并不重要。但重要的是,现在,我们的确实有一个子节点。
事实上,当使用空字符串运行 textContent setter 步骤时,目标元素的先前子元素将被删除,不会添加新节点,但仍会运行删除步骤。 但是,当目标元素中没有上一个子项时,不会删除任何节点,也不会添加任何新节点。插入步骤和删除步骤都不会运行,我们永远不会达到子级更改的步骤
TextNode<style><style>

因此,这一切都归结为当有没有以前的内容时如何以不同的方式运行。textContent = ""