写在最前

不想写英文了,费劲。

预期的样子

最近写的一个登陆界面,采用了还算比较火的Material Design来设计表单。简单点说就是当一个输入框没有内容且没有获得焦点,label提示就滑下来,否则label就会到左上角去。如果没有按照预期,就可能导致label提示和输入框内容在显示上重叠,极其难看。

所以其实只要监听focus和blur,在回调事件里再判断一下输入框值是否为空就行了。但是!

好了前面没听懂也无所谓,但是!

Chrome浏览器有记住密码功能,也就是在页面加载完成后,大部分JS运行完成后,填充账号密码框。这导致没有focus就改变了内容,超出了我的预期。没关系,我也很机智的想到了用change事件监听,也基本解决了。但是!

只解决了一半,账号框很顺利的监听到了change事件并做了正确的处理,而密码输入框则没有监听到change事件。这么说也不完全正确。

奇怪的表现

具体的情况是这样:

当鼠标点击了包含该表单的页面的任何地方(因为可能有多个frame),或者说和这个页面产生了任何交互,自动填充就会触发密码框的change事件,否则,只有账号输入框会触发change事件,而密码框则不会。复现方式:点击浏览器的刷新图标来刷新页面,此时用户没有和该页面交互,导致上面的现象发生。

我查了很多资料发现,这是Chrome故意设计的。事实上不仅Chrome,貌似IE也有类似的情况,其他浏览器未测试。原因是为了安全,当用户并没有与之交互时,自动填充密码其实是应该叫做“预填充”,只是看起来输入框里有内容了,但是DOM没有改变,输入框的value也没有改变,完全是浏览器行为,所以没有触发change事件监听器,这可能是为了防止在用户不知情的情况下,某不轨JS直接检测到密码然后泄露。不过似乎也不太说的通,我也没有深究,反正它破坏了我的样式,我很头痛。

具体相关情况可以参考 More info