锁定老帖子 主题:西方人通常发现不了的一个IE的bug
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-05-09
VML的一个严重问题)首次发现了这个Bug。经过一番狗狗之后,也未发现有同样的报告。后来我又逐渐在几种其他非VML的情形下重现了这个奇异的Bug。经过一番探究,我大致推断出了这个bug的原因。不过我一直没有公开发布过这个有趣的问题,只是跟少数同事提到过它。这个bug有个有趣的特点,就是西方人通常不会碰到这个bug。
这个问题我大概在一年多以前在某个用到VML的页面中(当时倒是记录了最近,真懒同学(realazy)在《认识延迟时间为 0 的 setTimeout》一文中举例说明setTimeout的用途。代码大意如下: $('myButton').onmousedown = function () { var input = document.createElement('input'); input.type = 'text'; $('myDiv').appendChild(input); input.focus(); } 在IE中,新创建的input没有如预期的获得焦点。 如果把input.focus()放在一个setTimeout中延时执行,则就可以获得焦点。 这个例子本身其实并不能证明realazy想要说明的观点,因为他不小心碰到了一个IE的微妙bug。在留言中,Lunatic Sun倒是敏锐的判断出这是IE的bug,只是这个bug的本质不是那么容易认识到,它其实并不是onmousedown本身的bug。 实际上,这是IE的focus机制的bug。 IE中的所有元素其实并不是被凭空绘制出来的,而是统统基于已有的Windows控件之上。除了典型的按钮、下拉菜单等,普通的div其实也是一个textbox控件。 所以IE的HTML focus等实际是被转换为windows控件的focus,于是在IE中存在两种不同层次的focus机制。理想上,HTML的focus应该被同步转换为windows控件的focus,然而IE可怜的代码导致这种转换存在许多bug。我们经常遇到的焦点虚线框丢失的问题其实就是一个例子。 实际上,在上面的例子中,表面上input没有得到焦点,但是其实调用focus()之后,HTML focus确实已经到了新生成的input中,这一点你可以通过document.activeElement来验证,你也可以按tab和shift-tab观察焦点的切换来证明这一点。然而,由于mousedown事件默认会获得控件焦点,所以windows控件focus就跑回了你的按钮上面了。这里出现了windows focus机制和html focus机制的脱节。显然IE在focus上的同步代码实在是太脆弱了。 事实上,IE对焦点的控制似乎本来就不和逻辑。所有的hasLayout元素都能获得焦点!结果一个页面上大部分区域在mousedown之后焦点就不知跑到哪个元素上了——这显然不是我们想要的行为——合乎HTML规范逻辑的行为应该是只有交互控件,如表单控件和A元素等,才能获得焦点。这导致一个典型的用户体验问题:在一个限制高度的可卷动区域中(例如一个长表单),拖动scrollbar,控件焦点就丢失——实际焦点跑到scrollbar所在的元素(例如form元素)上了。最严重的是,body元素一般总会有scrollbar!为了缓解这个问题,微软为body元素打了补丁,使得body上的scrollbar不会抢走焦点。然而IE这个patch打得实在是太烂了,在标准模式下,canvas从body变成了html元素,所以页面scrollbar就到了html元素上,结果bug又回来了! 撇开抢焦点问题,我们回到前面的话题。 既然html focus还是在input元素上,那么当时windows控件焦点到底跑哪里去了?实际上这个焦点跑到了mousedown所发生的对象上。比如如果是一个input按钮,焦点就会在该input按钮实际对应的windows的Button控件上。不过button元素的实现和一般的input不同,所以button元素上的mousedown之后,windows控件焦点实际上会跑到button元素外层的那个元素所对应的windows控件(通常是TextBox控件)中。 如何证明这一点?我过去用过一个调试工具可以显示出每个html控件实际的windows控件,也能查看实际的windows系统焦点。不过现在想不起来那个工具的名称了。搞笑的是,此处还会出现一个非常orz的症状——也就是本文标题所称的“西方人通常发现不了的一个IE的bug”——可以证明这一点。 focus问题 + 西方人通常发现不了。各位是否已经猜到了呢?大家不妨用realazy的那个页面中的第一个按钮来直接实验一把。 我会在下篇blog中继续聊这个话题。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-05-09
师傅~~~~~~~~~~ 受八戒一拜!!!
你是怎么发现这些的? 看过IE的代码? 哪有这些介绍浏览器低层机制和原理的文章呢?推荐一些资料吧 我自己看代码太累了 |
|
返回顶楼 | |
发表时间:2008-05-09
错错错!老大好象标题d了吧!
http://realazy.org/lab/settimeout.html 这个页面难道在FF下正常吗? 你把这些处理放到 onmouseup 里不就正常了吗!既然onmouseup 正常,原因也就猜差不多了吧! ---------------------- 其实我觉的处理事件应该放到mouseup中,其实操作系统之类的软件都是这样做的. 比如你下压鼠标,然后后悔了,怎么办.移动鼠标,释放鼠标,什么也不干了! |
|
返回顶楼 | |
发表时间:2008-05-09
错错错!老大好象标题d了吧!
http://realazy.org/lab/settimeout.html 这个页面难道在FF下正常吗? 你把这些处理放到 onmouseup 里不就正常了吗!既然onmouseup 正常,原因也就猜差不多了吧! ---------------------- 其实我觉的处理事件应该放到mouseup中,其实操作系统之类的软件都是这样做的. 比如你下压鼠标,然后后悔了,怎么办.移动鼠标,释放鼠标,什么也不干了! |
|
返回顶楼 | |
发表时间:2008-05-09
以前遇到过你说的问题,当时没有意识到原来是Bug以为自己的方式是错误的,说实话,IE给程序员带来了很多“尝试性的错误”
|
|
返回顶楼 | |
发表时间:2008-05-09
如果把那个button 换成div+ onclick...
就能很好的说明问题了 其实那个例子里 在IE下和FF主要的区别是 在IE里 按钮下按的效果 看不到 但是在其他浏览器里却能 |
|
返回顶楼 | |
发表时间:2008-05-09
down click up 这是事件处理的顺序
在down里做一些事情确实危险 例如 alert一个东西 那么click事件 就不能被正确的触发了 |
|
返回顶楼 | |
发表时间:2008-05-10
focus问题 + 西方人通常发现不了。
发现问题了没? 俺是不是有点标题党? |
|
返回顶楼 | |
发表时间:2008-05-10
不知道为什么 西方人发现不了
|
|
返回顶楼 | |
发表时间:2008-05-10
fins 写道 不知道为什么 西方人发现不了
开动脑筋啊。一样使用IE,我们跟西方人有什么区别呢? |
|
返回顶楼 | |