一个诡异问题的排查

这个问题本身其实不能称之为问题,记下来只是我觉得排查经历挺典型的,值得分享。

这个问题本身其实不能称之为问题,记下来只是我觉得排查经历挺典型的,值得分享。

先说下我的环境:MacOS 10.8.2 + Chrome 23.x + Bootstrap 2.2.1 + jQuery 1.8.2。事情是这样的,我本来在开发一个新功能,顺便把老页面重构一下,貌似一切正常。重构完毕后,我想随手测试一下重构后的页面,发现下拉菜单竟然不能点击了,或者说,点击完全失效了。

这让我很恐慌,因为类似的重构过程我近段时间来做的不是一次两次,这次我应该没有任何冒险的改动才是。这种情况下出现的Bug,一般都很棘手。于是,我打开以前的某个页面——同样经历了重构,但是通过了测试,并且在一顿时间的使用中完全没有问题——发现里面的下拉菜单同样点击失效了。于是,真正的排查开始了。

版本回溯

首先我当然去回溯近期的修改,看看会不会是某次改坏了。但综合几个文件看下来,都没有可疑的部分。因为重构涉及的文件不少,所以我并没有整个回退版本。接着我去查看线上的版本,发现是正常的。(线上域名是www.dianjoy.com,测试时域名是meathill.mac ,这是很关键的一个问题,不过我当时没想起来。)

我不想丢弃已经进行的工作,看代码又没看太出来,于是我开始调试。

分辨问题所在

我在鼠标点击事件处理函数上打了断点,以便排除代码故障。结果,当我点下菜单中的链接时,断点部分完全没有执行。

接着我怀疑是事件绑定阶段出了问题,于是我把断点提前到初始化阶段,发现绑定没有问题。并且,我把局部变量全局话,手工找到链接调用其click方法,功能正常。

既然绑定和触发都正常,那是某个层拦截了事件没?在开发者工具里找了半天,一无所获。

所以,现在几乎已经可以肯定,是事件的产生和广播中,某个环节出了问题。

寻找事件

于是乎,我给document增加了一个侦听器,我们知道,JavaScript里面UI事件默认是冒泡的,所以document的事件,一定都是某个较高层的标签点击后,一层一层传上来的。所以分辨event.target,就应该可以判断究竟是什么被点了。

测试结果,下拉菜单确实没有被点击,也如我排查的那样,并非有哪个层覆盖在上面,拦截了点击。点击都是被下拉菜单挡住的内容触发的。这说明,弹出菜单在点击事件出发前就已经被移除了。

那难道是mousedown,于是我侦听mousedown,结果一样。按理说不可能有哪个事件先于mousedown触发啊。好在我之前看过不少关于移动设备和触摸事件的东西,马上想到,难不成是触摸事件?可我这是普通网页跑在pc里啊,等等,难道……

我打开开发者工具的设置,里面“Emulate Touch Evens”的选项被勾选了,可能是我之前测什么的时候勾上的。取消勾选,测试,正常。至此,排错结束。

总结

原来是我让Chrome在“meathill.pc”这个域名下模拟触摸事件,所以点击后先触发了touch事件,使得弹出菜单被隐藏;接下来的点击事件只能被后面原本被遮挡的其它元素接收了。

事实上,这连个Bug都算不上,除了我,没人会遇到。不过我还有有所收获的:

  1. 确定问题,从大到小,从前到后,逐一排查
  2. 知识储备很重要,如果不了解事件触发的顺序,我也想不到这点了
  3. 太先进了也许未必是好事……

作者: meathill

爱编程,爱旅游,爱吐槽。 今年的目标是完成并运营至少一个 Side Project。 《Electron + Vue 实战开发》龟速创作中……

欢迎吐槽,请勿装死