js如何模拟表单输入

jQuery时代,模拟表单输入很简单,本质上就是操作dom,选择对于的dom,给dom.value设置值即可。

到了react时代就不同了,虽然也可以通过js拿到dom,给dom.value设置,但是react的状态绑定下,单纯给dom设置value,可是不会直接让react对于的状态也变化的。举个例子:

<input onChange={e=>console.log(e)} />

这么写一个react组件,通过js得到这个dom后dom.value=123;并不会触发onChange事件。

之前遇到过这个问题,不过没有深究,刚好同事分享到automa,发现automa靠选择器也能模拟表单填写,于是再研究了一下。

1. 原生分发事件其实是有的

如下:

// html
<input id="ninput" />

// js
var $dom = document.querySelector('#ninput');
$dom.addEventListener('change', e=>{
 console.log('trigger change', e, e.target.value);
})


// manual js
var $dom = document.querySelector('#ninput');
$dom.value = "123";
$dom.dispatchEvent(new Event("change", {bubbles:true}));

利用new Event 和 dispatchEvent就可以触发绑定事件

2. dispatchEvent能否也用在react组件上呢?

既然上面可以,其实理论上,应该也是支持的,先试试下面代码

// jsx
<input onChange={e=>console.log(e)} />


// manual js
var $dom = document.querySelector('#root input');
$dom.value = "123";
$dom.dispatchEvent(new Event("change", {bubbles:true}));

咦,怎么界面的input确实改成了123,但是没有console.log啊,也就是没有触发onChange

理论上,react上的事件虽然不是直接绑在dom,而是合成事件,但合成事件也是root上绑定的事件,等待冒泡上来的,new Event也设置了bubbles:true

后来在stackoverflow看到一个回答示例,改写了一下:

// jsx
<input onChange={e=>console.log(e)} />


// manual js
var $dom = document.querySelector('#root input');

const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
    window.HTMLInputElement.prototype,
    'value').set;
  nativeInputValueSetter.call($dom, '1234');
  const event = new Event('change', { bubbles: true });
  $dom.dispatchEvent(event);

用了另外一种方式给dom设置value

const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
    window.HTMLInputElement.prototype,
    'value').set;
  nativeInputValueSetter.call($dom, '1234');

触发了console.log,但是 如果重复设置同一个值,也是不会触发到onChange的。

参考:reactjs - What is the best way to trigger change or input event in react js - Stack Overflow

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值