浏览器自动化填表单总是不生效?聊聊受控组件与原生 setter
问题现象
用脚本往输入框里写值,肉眼看着值已经进去了,但一点提交就报「请输入 xxx」,或者提交后后端收到的还是空值。
这类问题在前端框架(Vue / React)的受控组件上非常普遍,和点得准不准没关系。
根因
受控组件的真实数据源不是 DOM 的 value,而是框架内部的状态。
直接写:
input.value = 'hello'
DOM 的值变了,但框架状态没变。框架下一次渲染时会把 DOM 的值覆盖回它自己状态里的旧值。于是:
- 校验读的是框架状态 → 判定为空
- 提交读的是框架状态 → 后端收到空
正确写法:原生 setter + 派发事件
关键是不能用元素上的 value setter(部分框架会劫持它),要用原型上的原生 setter,再手动派发 input 事件让框架感知:
function setNativeValue(el, value) {
const proto = el instanceof HTMLTextAreaElement
? HTMLTextAreaElement.prototype
: HTMLInputElement.prototype;
const setter = Object.getOwnPropertyDescriptor(proto, 'value').set;
setter.call(el, value);
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
}
input 事件是 React 的 onChange 和 Vue 的 v-model 共同的监听入口,两个事件都派发一遍最稳。
几个变体
1. 富文本与代码编辑器
CodeMirror、TinyMCE、MUI 的多行输入都不吃上面那套,它们各自有 API:
// TinyMCE
tinymce.get('editor').setContent(html);
tinymce.get('editor').fire('change');
CodeMirror 6 通常要先 focus,再走 paste 事件或 execCommand('insertText')。
2. 隐藏的 checkbox
不少 UI 库把 <input type="checkbox"> 设成 opacity: 0 覆盖在自定义图形上。此时 elementFromPoint 命中的是 input,但 .click() 不一定触发框架逻辑,得用真实鼠标事件。
3. 按钮点了没反应
如果按钮是 <a> 且没有 href、靠 JS 绑定事件,.click() 可能不触发。优先按坐标发真实鼠标事件;再不行就去读页面发出的网络请求,直接调后端接口。
判断顺序
- 先用
input事件那套,能解决八成 - 不行就找框架的官方 API(编辑器、下拉框大多有)
- 还不行就抓网络请求,直接调后端接口
- 最后才考虑真实鼠标事件模拟
小结
自动化填表失败,九成不是「没点对」,而是「没让框架知道值变了」。理解受控组件的数据流向,比反复重试点位有效得多。
- 点赞
- 收藏
- 关注作者
评论(0)