自动填充不会触发onChange

时间:2019-03-19 15:29:48

标签: javascript html reactjs dom autofill

我有一个登录表单,当页面打开时,Chrome会自动填写凭据。但是,没有触发onChange个元素的input事件。

点击页面上的任意位置,即可将它们注册到value的{​​{1}}属性中,这正是我们所需要的。我尝试做input,但没有帮助。

在onChange中,将值设置为如下状态:

event.target.click()

如果this.setState({ email: event.target.value }) ,则提交按钮被禁用。

因此,即使页面显示凭据已满,“提交”按钮仍然被禁用。

由于单击任意位置都会注册值,因此单击提交按钮也会在提交之前注册它们。因此,它运作完美。

尽管与时间无关,但从未填充字段。当我打开开发者控制台并检查时,值字段为空,直到单击某处。

这里唯一的问题是,该按钮看上去已禁用,因为在单击某些内容之前,电子邮件输入值是空的。是否有针对性的解决方案?

7 个答案:

答案 0 :(得分:2)

答案是要么在表单中使用autocomplete =“ off”禁用表单的自动完成功能,要么定期轮询以查看其是否已填充。

问题是自动填充由不同的浏览器进行不同的处理。 有些派遣变更事件,有些则没有。所以几乎是不可能的 挂钩事件,该事件在浏览器自动完成时触发 输入字段。

  • 更改不同浏览器的事件触发:

    • 对于用户名/密码字段:

      1. Firefox 4,IE 7和IE 8不会调度更改事件。
      2. Safari 5和Chrome 9确实分发了更改事件。
    • 对于其他表单字段:

      1. IE 7和IE 8不会调度更改事件。
      2. 当用户从建议列表中选择一个值并跳出字段时,Firefox 4确实调度了更改更改事件。
      3. Chrome 9不会调度更改事件。
      4. Safari 5确实调度了更改事件。

您最好的选择是使用禁用表单自动完成功能 autocomplete="off"在您的表单中或定期轮询以查看 如果已填充。

关于是否在文档上或文档之前填写的问题 同样,它因浏览器而异,甚至版本也不同。 仅在您选择用户名密码时才用于用户名/密码字段 字段已填写。因此,如果您总共将有一个非常凌乱的代码 尝试附加到任何事件。

您可以对此进行很好的阅读 HERE

看看这个线程:Detecting Browser Autofill

答案 1 :(得分:2)

我偶然发现了这个问题,因为我遇到了同样的问题。不是在React中,而是普遍存在的问题。也许这会帮助那些偶然发现此问题的人。

没有其他答案可以真正回答问题。 OP所描述的问题是,Chrome不会设置输入的值,除非用户与页面进行了交互。这可以单击页面,甚至可以在控制台中键入随机内容。

发生用户交互后,将设置输入的值并触发更改事件。

您甚至可以从视觉上看到这一点,因为自动填充文本的样式在首次显示时是不同的,并且在进行交互后会更改输入的样式。

此外:触发点击或设置焦点或代码中的任何内容都无济于事,只有真正的人机交互。

因此,轮询该值不是解决方案,因为如果未单击页面,则该值将保持为空。还指出您不能依赖change事件并没有真正意义,因为在延迟设置值后会正确触发事件 。问题是无限期的延迟。

不过,您可以轮询是否存在Chrome的伪CSS类。在Chrome 83(2020年六月)中,它们是:-internal-autofill-selected:-internal-autofill-previewed。但是,这些确实会定期更改。同样,它们在渲染后不直接存在。因此,您应该设置足够的超时时间或对其进行轮询。

原始JavaScript中的草率示例:

var input = document.getElementById('#someinput');

setTimeout(() => {
   if (input.matches(':-internal-autofill-selected')) {
      /* do something */
   }
}, 500);

此时您仍然无法获得该值,因此就此而言,它仍然无法解决问题,但是至少您可以基于自动填充数据的存在启用提交按钮(因为OP希望做)。或做一些其他视觉操作。

答案 2 :(得分:1)

event.target.click()将“模拟”一次点击并触发onClick()事件,但并不像浏览器窗口中的实际点击那样。

您是否已尝试使用focus()代替click()(或除了click()之外)?您可以尝试将焦点放在输入元素上,然后检查是否设置了该值。如果可行,您可以在焦点和点击上添加this.setState({ email: event.target.value })

答案 3 :(得分:0)

我在这里创建了一个示例应用程序 https://codesandbox.io/s/ynkvmv16v

这可以解决您的问题吗?

答案 4 :(得分:0)

无需触发点击事件,我认为,如果像这样在email中设置componentDidMount状态,那就更好了

this.setState({ email: document.getElementById('email').value })

因此,一旦调用componentDidMount(),您将得到Chrome浏览器填充的电子邮件并更新state,然后呈现“提交”按钮并将其启用。

您可以在此link

上了解有关React生命周期的更多信息

答案 5 :(得分:0)

使用oninput代替onchange可以解决问题

答案 6 :(得分:0)

如果通过自动填充在表单中填写数据,而您尝试直接提交表单,则像 Firefox 这样的浏览器不会获取输入数据,因为它不在该输入状态。

但如果您使用基于类的组件,我们可以在 useEffect 钩子或 componentDidMount 中解决它。

useEffect(() => {

 setUserName(document.getElementById('username').value);

}, [])

setUserName 这里是状态集方法,替换成你的。 使用输入字段的 ID 更改用户名。