背景
这几天遇到这么个需要,在输入框有值且鼠标悬浮的时候显示clearable按钮,否则不显示。
需要自身并没有什么特地的,我的项目用的vue2,只有在触发悬浮事件的时候检测绑定的值是否不为空即可。然而在login页面的时候却发现,页面初始加载之后,输入框里看似有值,然而绑定的v-model值却是空。
这理论就是浏览器主动填充的值(字体大小不同,且有个蓝色背景)。
这个问题其实大家在开发中或多或少应该都遇到过,简略举几个栗子:
- 想去除主动填充的背景色
- 如下图一样悬浮label被遮挡
- 像我遇到的问题一样,看似有值理论获取不到
剖析
查阅了一些材料,失去了一些对于autofill的信息
- 各个浏览器对于autofill的实现并不相同,这里只以chrome为例
- 当主动填充产生时,chrome并不会派发包含change事件在内的任何事件
- 因为没有事件的派发,所以也不可能通过js捕捉到autofill的事件
- 因为autofill是由浏览器管制而非实在用户触发,所以这不是个isTrusted的行为
- 因为这不是个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...