前言
今天有同学向我问了在killCube中遇到的BUG。
最终的原因是有关Node.childNodes
的使用不当造成的。
本文做些记录。
重现BUG
1 | <main id="main"> |
1 | function move( ) { |
在以上代码中,move()函数中其中一部分逻辑是指 当 <div id="con">
的子节点长度为5时,且另一个逻辑rows[rows.length-1].pass!==1
为真时,调用fail()
函数,游戏结束。
可这位同学以上的代码,却不能让游戏正常结束。
问题就出现在那段注释上,会导致con.childNodes.length
在游戏的一开始就40+,远远超过了5,所以游戏不会结束。
具体分析
分有注释和没有注释的两种情况进行讨论
没有注释
1 | <div id="con"></div> |
1 | function $(id) { |
以上结果很容易理解,con节点并没有子节点
现在将HTML结构进行一些改变
1 | <div id="con"> </div> |
这样就有了一个子节点了。
因为childNode将(空格,tab,换行等也计算了进去)
当然具体到空格还是回车换行等具体节点,它们的data
属性还是不同,这里不做介绍。
引入注释
1 | <div id="con"> |
这种情况下,con节点有了三个子节点,除了两处的换行,注释也成为了一个节点
问题总结
回到最初的问题我们可以得出结论
这位同学在HTML引入了空白以及换行符,导致子节点的个数远远增加,而不是预期的0,导致不能满足游戏结束的条件。而killCube中,子节点是通过脚本动态写入的,没有空格回车注释等,故不存在上述问题。
有的时候,bug往往是因为HTML、CSS没写好造成的,导致需要写更多JS去维护。
childNodes与children
Node.childNodes
返回包含 指定节点的子节点的集合 ,该集合为即时更新的集合(live collection)
。
ParentNode.children
是一个只读属性,返回 一个 Node
的子elements
的活 HTMLCollection
。
ParentNode.children
只返回 元素 的集合,因此使用ParentNode.children
可以避免之前的问题出现
有关nodeType可以看看这儿。
封装
ParentNode.children
只适用于nodeType
为1的节点。
我稍微封装了一下,可以根据自己的需求使用
1 | let getXNodes = (parentNode) => { |