同一个页面两套输入框:querySelector 填了值,页面却说没填
一个登录页,手机号框用脚本填值,控制台里读 input.value 明明是 18813346340,页面上的「获取验证码」按钮却一直灰着,提示「请先输入手机号」。这篇记录排查过程,以及最后怎么找到页面上真正的那个输入框。
现象
华为云登录页,两套输入框:一套 input[name=username],一套 input.hwid-input。用 document.querySelector('input[name=username]') 拿到元素,setVal 填值成功,读回 value 也对。但「获取验证码」按钮的 class 里始终带着 hwid-disabled,点击派发五种鼠标事件(pointerdown、mousedown、pointerup、mouseup、click)全都没反应,网络请求一条没发。
第一个怀疑:值没进框架
换原生输入:focus、全选、Backspace 清空,再用逐字符按键输入 11 位手机号。框架一般监听 input 事件,原生按键一定触发。结果 value 还是那个 value,按钮还是灰的。
第二个怀疑:按钮自身问题
检查按钮:disabled 属性是 false,pointer-events 是 auto,没有任何遮挡弹窗,控制台也没有报错。点击处理函数确实存在——class 变化说明框架在校验手机号,只是校验结果一直是空。
转折点:elementFromPoint
用 document.elementFromPoint(1541, 445) 查这个坐标上的元素——坐标来自输入框自己的 getBoundingClientRect()。返回的不是那个 input,而是一个 1920x45 的顶部横幅。
换 document.elementsFromPoint(复数)列出这个点的整条层叠链,真相出来了:
- INPUT.hwid-input 285x46 ← 最顶层,真实输入框
- DIV.hwid-input-root 285x46
- DIV.hwid-input-area 400x48
- DIV.hwid-widget-input 400x48
- …下面还有七八层容器
再全页搜 input.hwid-input,返回四个:账号密码登录的 userAccount(0x0)、密码框(0x0)、手机号框(285x46)、验证码框(398x46)。页面上有两套完整登录 UI,一套是隐藏的旧版(querySelector 默认按文档顺序先命中它),一套是当前展示的新版。
为什么 focus 也不行
对隐藏 input 调 focus(),document.activeElement 依然是 BODY——宽高为 0 的元素焦点进不去。这就是判定依据:focus 之后检查 activeElement 是不是它自己,不是,就说明你拿到的不是页面上那个框。
三步定位法
- 先拿目标输入框的 getBoundingClientRect,得到中心坐标;
- 用 document.elementsFromPoint(x, y) 列出该点全部元素,从上往下找第一个 INPUT;
- 对它调 focus(),确认 document.activeElement === 它,再用原生按键输入。
这次用这套流程:focus 返回 true,逐字符输入手机号,hwid-disabled 类当场消失,「获取验证码」可以点了,验证码也正常发出来了。
总结
querySelector 命中的元素和页面上可见的元素可能根本不是同一个。填值、派发事件之前,先做两个验证:getBoundingClientRect 的宽高是不是 0;focus 之后 activeElement 是不是它自己。两关都过了,再谈输入。宽高 0 的元素就是给爬虫和自动化脚本准备的陷阱副本,页面上渲染的永远是另一份。
- 点赞
- 收藏
- 关注作者
评论(0)