背景

这几天遇到这么个需要,在输入框有值且鼠标悬浮的时候显示clearable按钮,否则不显示。

需要自身并没有什么特地的,我的项目用的vue2,只有在触发悬浮事件的时候检测绑定的值是否不为空即可。然而在login页面的时候却发现,页面初始加载之后,输入框里看似有值,然而绑定的v-model值却是空。

这理论就是浏览器主动填充的值(字体大小不同,且有个蓝色背景)。

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

  1. 想去除主动填充的背景色
  2. 如下图一样悬浮label被遮挡
  3. 像我遇到的问题一样,看似有值理论获取不到

剖析

查阅了一些材料,失去了一些对于autofill的信息

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

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

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

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

解决办法

咱们能够看到主动填充的输入框里的款式变了,关上F12,往下拉,就能够看到

好了,想解决主动填充背景色的敌人,能够用这个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...