需求:类似 LastPass 这种可以自动填充用户名密码,点击提交
难点:很多现代化的页面前端做了表单校验,直接赋值 input 的 value 不能通过表单校验
关键在于没能触发人家框架的 event listener
查资料咯,发现了这个解答 https://stackoverflow.com/a/35807417 就是触发 input 、keyup 、change 事件,但实际测试仍然不行,甚至我把在开发人员工具能看到的 event listner 全触发了一边都没用 sad
function fireChangeEvents(element){
var changeEvent = null;
for(var i of ["keypress","focus", "input", "keydown", "keyup", "change", "blur", "click", "invalid", "mouseover", "popstate", "reset", "scroll", "selectionchange", "submit", "transitionend"]){
changeEvent = document.createEvent ("HTMLEvents");
changeEvent.initEvent (i, true, true);
element.dispatchEvent (changeEvent);
}
}
fireChangeEvents(document.querySelectorAll("input")[0])
然后接着找,发现一个能模拟用户交互的 npm 包: https://github.com/testing-library/user-event
然后折腾了一下 browserify 打包成浏览器可以用的 js 文件,实际测试可行:
userEvent.type(document.querySelectorAll("input")[0], USERNAME);
userEvent.type(document.querySelectorAll("input")[1], PASSWORD);
问题是解决了,但觉得为了一个触发 event 引入一个 500KB 的 js 文件有点蠢( uglify 之后也有 300KB ),问问大佬们有没有更好的方案,不需要引入这么重的 js 库的
4L解决了这个问题, 感谢CoolSpring大佬
解决方案写到了我的blog里,欢迎顺手访问一下: https://blog.chenyuan.me/JavaScript/#tampermonkey
1
iNaru 2020-08-27 00:57:39 +08:00 1
input.dispatchEvent(new Event('input', { bubbles: true }));
|
3
cy97cool OP https://ant.design/components/form-cn/
找到一个可以用来验证的例子,这个页面中的 嵌套结构与校验信息 部分,Username 右边有个 Need Help?的链接 对这个 input 右键 检查元素,在 Console 里输入 $0.value="1" , 然后点击这个表单的 Submit,会报错“Username is required”。 问题就是:在 Console 里输入啥神奇的代码,能成功通过这个表单的检查 |
4
CoolSpring 2020-08-27 09:53:31 +08:00 2
如果是 React,似乎可以用这个: https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js
var input = document.getElementById("complex-form_username"); var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; nativeInputValueSetter.call(input, 'react 16 value'); var ev2 = new Event('input', { bubbles: true}); input.dispatchEvent(ev2); |
5
cy97cool OP @CoolSpring 感谢 确实有用
|
6
Damon3621 2020-10-20 14:06:05 +08:00
Hi 兄弟 请问你如何获取页面中的 input 框呢?我最近也在写自动填充插件,遇到问题了。 比如腾讯视频 他的 Input 框放在 iframe 框架里,调用的话不是会跨域吗
|
8
Damon3621 2020-10-21 14:11:29 +08:00
@cy97cool 大佬,可以说的具体点嘛 我现在能获取这个 iframe 的 url 但不能操作里面的 dom 怎么对这个 url 启用脚本呢
|
9
cy97cool OP |
11
Jonatvtwoex 2020-11-23 17:48:45 +08:00
原因是校验逻辑依赖 input 事件, 而 inputEle.value = xxx 并不会触发 input 事件
const inputEle = document.querySelector(`input[name=${key}]`) inputEle.value = fields[key] // 关键代码: input 元素在事后触发一下 input 事件 inputEle.dispatchEvent(new Event('input')); |