今天同事 明城 在项目中碰到一个 BUG,代码具体如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>Firefox下innerHTML的一个BUG</title>
<style type="text/css">
    a { display: block; border: 1px solid red;}
    div { display: inline; border: 1px solid red;}
</style>
</head>
<body>
<a href="javascript:change();">change<div id="count">20</div>aaa</a>
<script type="text/javascript">
function change() {
    var count = document.getElementById('count');
    var c = count.innerHTML;
    var page = parseInt(c)+1;
    count.innerHTML = page;
    alert(page);
}
</script>
</body>
</html>

当你在 Firefox2.0+ 或 Firefox3.0+ 中点击链接后,会发现 innerHTML 插入的内容为<a>21</a>,而其他浏览器测试(IE6、IE7、Safari3.0+、Opera9.0+)都正常,插入内容均为文字 21。

估计是 Firefox 的一个 BUG,查找了官方网站的 BUG库,果真找到别人提交的该类问题——《Setting innerHTML on a block element inside an inline element creates extra copies of the inline element》(Bug 381808)。

我们可以参阅下8楼的 Boris Zbarsky 给出的个人解释:

There are two separate concepts of block vs inline. One in CSS and one in
HTML. They don't match.

In any case, the point is that in HTML <b> is not allowed to contain <div> (so
the <b> needs to get closed), but the text needs to be bold for compat so we do
residual style handling. HTML5 is going to define a different method of doing
this anyway, so at that point we'll need to revisit this bug.

虽然这是一个 BUG,但 BUG 的造成也却是人为的不良习惯造成的,在 WEB 标准中严格来说内联元素是不允许包含块级元素的(扩展阅读:《Allowed nesting of elements in HTML 4 Strict (and XHTML 1.0 Strict)》)。



共有18 条评论

  1. 1. 头像 MacJi

    可以忽略的bug,不可忽视的“人为的不良习惯”。

  2. 2. 头像 怿飞

    最后的扩展阅读也可以看 Junchen 写的《(X)HTML Strict 下的嵌套规则》

  3. 3. 头像 青色

    你好,博主!你那个源代码的地方是否用了什么插件?如果用了,可否告知是什么插件,或者发到我的邮箱,谢谢!

  4. 4. 头像 MarVell

    这结构。。。只能说FF太严格。。。

  5. 5. 头像 角落阳光

    根据xhtml规范,行内元素可以继承块级元素,反过来就不行。《css权威指南》一书如是说的。

  6. 6. 头像 手气不错

    这是在帮同事 review 代码的时候发现的,当时改成 span 就解决了问题,不过我不能解释这个原因,感谢“怪飞”同学~

  7. 7. 头像 tokki

    =.= a里面套个DIV是过不了W3C的 从不这样搞=。=

  8. 8. 头像 怿飞

    @青色 没有用插件,仅用的原生的标签:pre和code

  9. 9. 头像 秦歌

    其实这个问题是普遍遇到的,不仅仅是在利用JavaScript时会有这样的问题,某些情况下对CSS也会有较大的影响。所以使用语义的严格的HTML是非常有必要的。http://dancewithnet.com/2007/06/21/xhtml11_tags_list/这里有所有的HTML标签父子关系列表。

  10. 10. 头像 rainaxin

    养成良好书写代码习惯,很多bug其实是可以避免的!

  11. 11. 头像 怿飞

    @秦歌 是的,理解语义,掌握嵌套规则,是作为前端最基本的要求,谢谢你提供的链接,很有价值^^

  12. 12. 头像 lolocoo

    难道是我浏览器的毛病,我这ff3怎么出现了NaN值啊?

  13. 13. 头像 怿飞

    @lolocoo NaN值就对了parseInt处理的不是数字开头的,而是a元素开头的

  14. 14. 头像 啸沧海

    恩w3c标准的问题
    用span替换div解决吧.

  15. 15. 头像 八度社区

    我一帮都会用jquery,兼容性比较好,能够实现统一的效果

  16. 16. 头像 怿飞

    知其然知其所以然也是有好处的,呵呵

  17. 17. 头像 Carrien

    恩恩。把div换成span 就OK了

  18. 18. 头像 webscript

    document.getElementById(‘count’).innerHTML是string型
    document.getElementById(‘count’).innerHTML = page 右边是number型
    最后得到结果document.getElementById(‘count’).innerHTML 是 string
    但:
    var m=”mm”
    m=21
    最后得到结果是m是number
    奇怪

发表评论

(必填)

(必填,会为您保密)

评论仅支持“a、abbr、strong、em、blockquote、code”几个简单的标签