Js检测chrome autofill

背景

这几天遇到这么个需求,在输入框有值且鼠标悬浮的时候显示clearable按钮,否则不显示。
Js检测chrome autofill_第1张图片
需求本身并没有什么特别的,项目用的vue2,只要在触发悬浮事件的时候检测绑定的值是否不为空即可。但是在login页面的时候却发现,页面初始加载之后,输入框里看似有值,但是绑定的v-model值却是空。
image.png
这实际就是浏览器自动填充的值(字体大小不同,且有个蓝色背景)。

这个问题其实大家在开发中或多或少应该都遇到过,简单举几个栗子:

  1. 想去除自动填充的背景色
  2. 如下图一样悬浮label被遮挡
    Js检测chrome autofill_第2张图片
  3. 像我遇到的问题一样,看似有值实际获取不到

分析

查阅了一些资料,得到了一些关于autofill的信息

  1. 各个浏览器对于autofill的实现并不相同,这里只以chrome为例
  2. 当自动填充发生时,chrome并不会派发包括change事件在内的任何事件
  3. 由于没有事件的派发,所以也不可能通过js捕捉到autofill的事件
  4. 因为autofill是由浏览器控制而非真实用户触发,所以这不是个isTrusted的行为
  5. 因为这不是个trusted的行为,所以我们不能通过js读取到autofill的值,直到真实用户动作

听起来有点绕,没关系,简单总结一下主要有两点:

  • chrome自动填充的时候不会触发任何事件,所以js也捕捉不到
  • 自动填充的值也不能被js取到

那么我们就没办法检测到autofill了吗?
漏漏漏,其实答案就在眼前

解决方法

我们可以看到自动填充的输入框里的样式变了,打开F12,往下拉,就可以看到
Js检测chrome autofill_第3张图片

好了,想解决自动填充背景色的朋友,可以用这个css覆盖这个伪类:
input:-internal-autofill-selected

接下来说一下在js里怎么解决这个问题

观察一下此处有个特殊的css属性appearance,试验了一下autofill的状态,appearance属性的值是menulist-button。手动输入的时候appearance的值是auto。
我们可以利用这个属性来实现对autofill的检测

简单的写一个方法:

const detectAutofill = (element) => {
  return window.getComputedStyle(element, null).getPropertyValue('appearance') === 'menulist-button'
}

然后在页面初始化的时候加一个延时来调他,试验了一下600ms左右基本可以调到,所以给个默认值延迟600ms

const detectAutofill = (element, timeout=600) => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(window.getComputedStyle(element, null).getPropertyValue('appearance') === 'menulist-button')
    }, timeout)
  })
}

使用方法示例:

async testAutoFill () {
  this.autofilled = await detectAutofill(this.$refs.input)
}

参考资料:
https://dom.spec.whatwg.org/#...
https://kishoreconnect.com/ja...
https://medium.com/weekly-web...

你可能感兴趣的:(Js检测chrome autofill)