IE下JS childNodes属性的疑惑



 

<div id="test"> <i>test</i> </div>

 var test = document.getElementById("test");

alert(test.childNodes[1].nodeType);

IE 下弹出 3,难道 i 标签后面的空文本也算进去了
IE 不是会忽略空文本节点的吗? i 标签前面的空文本就没算进去啊!
但是吧 i 标签换成其他的 div , p 标签之类就正常的,
但是 i 标签, em 标签, b 标签之类的改变字体样式的标签就会出现这个问题,
这是为什么呢,左右不对称啊

浏览器 JavaScript internet-explorer

坑爹么这是 10 years, 9 months ago

W3Help处 有详细的实验过程。

要注意到,IE下, 会影响到渲染的 空文本节点都没有忽略,比如说,行内标签之间的空白节点。在W3C标准中,行内标签之间的空白节点,必须根据white-space属性进行判断,影响渲染。


下面详细解释会影响到渲染的空文本节点。让我们从空白符开始吧。

W3C 9.1 White space 规定了以下字符为空白符:

  • ASCII 空格
  • ASCII 制表符
  • ASCII 换页符
  • 零宽度空格
  • 折行(line-break)
通常情况下,对于多个连续的空白符(空格,换行符,回车符等),浏览器会将他们合并为一个空白符。CSS 中由 white-space 这个属性来控制:
  • normal:默认处理方式。
  • pre:用等宽字体显示预先格式化的文本,不合并文字间的空白距离,当文字超出边界时不换行。可查阅 pre 对象
  • nowrap:强制在同一行内显示所有文本,直到文本结束或者遭遇 br 对象。
  • pre-wrap:用等宽字体显示预先格式化的文本,不合并文字间的空白距离,当文字碰到边界时发生换行。
  • pre-line:保持文本的换行,不保留文字间的空白距离,当文字碰到边界时发生换行。
——《 inline-block 前世今生

在接下来的 W3C 16.6.1 The 'white-space' processing model 里讲到空白符是如何参与渲染策略的:

下面是我对标准的翻译

对于每个inline元素(包括匿名的inline元素),下列步骤被执行:

  1. white-space 设为 normal , nowrap pre-line U+000A (linefeed)周边的 U+0009 (tab)、 U+000D (carriage return)、 U+0020 (space)被舍弃
  2. white-space 被设为 pre pre-wrap ,任何不被元素边界破坏的空格序列 U+0020 被当做不折行的空格。然而,对于 pre-wrap 属性来说,在空格序列末尾有可能出现折行
  3. white-space 设为 normal nowrap ,在不一样的UA相关的上下文中,linefeed字符可能被当做空白符中的任意一个,或者没有字符(因此而不被渲染)
  4. white-space 设为 normal , nowrap pre-line ,tab字符被转化为空格;同时任何空白符之后的空白符——甚至是inline元素之前的 white-space ,只要该white space被应用了 white-space:normal | nowrap | pre-line ——会被移除

然后内联元素被排版下来,根据bidi信息被重新排序,然后按照 white-space 属性被包裹(wrap,可以理解为放进块级元素内部)起来。包裹过程中,按照 white-space 属性考虑是否折行。

每行的排版过程中:

  1. white-space 设为 normal , nowrap pre-line ,行首的空格被舍弃
  2. 所有的tab被渲染为一行的水平位移,直到下一个tab stop处。tab stop出现在每个块级的content-edge开始的每8个空格处
  3. white-space 设为 normal , nowrap pre-line ,行尾的空格被舍弃
  4. white-space 设为 pre-wrap ,行尾的空格和tab可能被UA折叠

浮动定位和绝对定位元素没有新的折行可能。


IE对空白符的解析,正好避免了可能影响到渲染的部分,去掉的空白符是空格在渲染环节被舍弃的部分(非全部,比如行末空白符就被保留了)。

两个过程本不应该混淆:决定空白符是否出现在DOM树中的这一步,发生在构建DOM树的阶段;决定空白符是否被渲染的这一步,发生在构建Rendering树阶段。
这个bug的影响,在于DOM而非CSS,具体而言,遍历childNodes时会有浏览器差异,做额外的判断即可。对于渲染没有区别。

P.S. M$的C++程序员对性能的焦渴导致他们在HTML parse阶段也有意识地控制DOM树大小?

跳坑的废柴 answered 10 years, 9 months ago

Your Answer