共计 1402 个字符,预计需要花费 4 分钟才能阅读完成。
背景
这几天遇到这么个需要,在输入框有值且鼠标悬浮的时候显示 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…