如何解决 chrome 自动完成与 vuetify 中的标签重叠的问题?

How fix issue with chrome auto complete overlap with labels in vuetify?

在 Vutify 中尝试使用 outlined 文本字段创建登录表单时,chrome 自动完成与 labels

重叠
<v-text-field
  v-model="email"
  label="e-mail"
  name="email"
  outlined
  prepend-icon="mdi-account"
  type="text"
  required
>
</v-text-field>

可以重新生成here请填写并提交,然后返回。

浏览器上的自动填充功能通常通过直接设置相关字段的值来工作。在这种情况下,字段的标签仅在输入字段获得焦点时才移开,而在与字段中的值模糊时则远离。在自动填充的情况下,焦点事件不会被触发,因此标签保持在原处。

要解决此问题,您必须(或让某人)在 Vuetify 中进行更改。

你可以给你的输入一个 id 并在安装组件时读取输入的值,如果它不是空的,那么你可以将你的数据值设置为输入所持有的那个值,这样标签就会正如你所期望的那样上升。根据您最近的评论,您似乎还需要等待 DOM 更新,因此我们能做的最好的事情就是在 nextTick:[=12 的帮助下进行检查=]

mounted()  {
  this.$nextTick(() => {
     const emailValue = document.getElementById('email').value;
     this.email = emailValue || '';
  });

}

好的,所以我所做的是这样的:

在输入上

:placeholder="!autofilled ? ' ' : ''"

在脚本中

data() {
        return {
            form: {
                email: '',
                password: '',
            },
            error: null,
            autofilled: false,
        };
},
watch: {
    'form.email'() {
        this.autofilled = true;
     },
},

它的作用:基本上将占位符设置为一个空白 space 总是“提升”标签。不幸的是,静态设置它会使标签无法返回,即使您在填充后清空输入。所以我所做的是使占位符动态化,并且在该占位符恢复为空后对输入进行任何更改之前仅将其设置为空白 space 。 它并不完美,因为在用户保存密码之前的初始加载时,标签会被提升,但我还没有发现比这更好的东西。

另一种方法是像@elazard 那样定义建议 像这样的自动填充变量

data () {
        return {
            login: null,
            password: null,
            autofill: false,
            intervalDetectAutofill: null
        }
    },
<v-text-field
    v-model="password"
    type="password"
    label="Password"
    :placeholder="autofill ? ` ` : null"
/>

用@adam-reis给出的,在登录页面的mounted()

mounted () {
        // search for autofill every 100ms
        this.intervalDetectAutofill = setInterval(() => {
            if (document.querySelectorAll("input[type=\"password\"]:-webkit-autofill").length > 0) {
                this.autofill = true
            }
        }, 100)

        // clean interval if needed after 3s
        setTimeout(() => {
            if (this.intervalDetectAutofill) {
                clearInterval(this.intervalDetectAutofill)
                this.intervalDetectAutofill = null
            }
        }, 3000)
    },

当然,如果用户输入,则将自动填充设置为 false

watch: {
        password () {
            this.autofill = false
        },
        autofill () {
            // clean interval if autofill detected or user input
            if (this.intervalDetectAutofill) {
                clearInterval(this.intervalDetectAutofill)
                this.intervalDetectAutofill = null
            }
        }
    },

我就是这样解决这个问题的。

看来我们的主要问题有以下几点:

  • 来自 Chrome 的自动填充,在加载页面时,没有让界面做出反应,让设计像您的图像一样。
  • 所以在注入的时候,我们应该自己做一个修复,但是没有事件,来自Chrome,可以在login/password被自动填充时通知我们。

有趣的是,来自浏览器的任何点击 window FROM USER 会自动通知反应性并且一切正常,但 FROM trigger/dispatch 内部方式不起作用。

所以首先,我们需要找到一种在 login/password 自动填充后做出反应的方法。 其次,我们需要自己修复设计,因为只有 FROM USER 操作才能使设计再次正常工作。

1.在加载页面自动填充后做出反应

我用的是第一种方案:

export default {
  //...
  data() {
    return {
      //...
      autofillFix: false,
    }
  },
  //...
  mounted() {
    this.autoLoginCheckingInterface()
  },
  //...
  autoLoginCheckingInterface() {
    // each 100ms we check if the issue was produced
    let intervalDetectAutofill = setInterval(() => {
      if (
        // we target at least one of the stuff that will be affected by autofill
        // to do our checking
        document.querySelectorAll('input[type="password"]:-webkit-autofill')
          .length > 0
      ) {
        // and we inform the system about the issue if it is produced
        this.autofillFix = true

        // we stop to check if issue was produced
        clearInterval(intervalDetectAutofill)
      }
    }, 100)

    // if after 3s nothing appear, means no autofill was made
    setTimeout(() => {
      if (intervalDetectAutofill) {
        clearInterval(intervalDetectAutofill)
        intervalDetectAutofill = null
      }
    }, 3000)
  },
  //...
}
<!--
we will inject `.autofill-fix` class to be able fix design ourself at time of this bug occur
--> 
<v-text-field
      ...
      :class="{ 'autofill-fix': autofillFix }"
      ...
      label="Email address or username"
      ...
      dense
      outlined
      @focus="autofillFix = false"
/>
<!--
we use @focus to let the normal behavior take again the lead
because we know this USER ACTION will made Chrome work well again
-->
<v-text-field
      ...
      :class="{ 'autofill-fix': autofillFix }"
      ...
      label="Password"
      type="password"
      ...
      dense
      outlined
      @focus="autofillFix = false"
/>

2。自行修复设计

我们可以看到当v-text-field填满后有什么变化。没有内容,我们可以看到这个:

自动填充后,我们可以看到:

所以从红色的部分我们可以看出需要定时注入如下代码 .autofill-fix 的存在以正确的方式修复设计

.autofill-fix.v-text-field--outlined.v-input--dense .v-label {
  left: -28px!important;
  transform: translateY(-16px) scale(.75);
}

注意:如果不使用 outlineddense,则需要更改 CSS 选择器。注意选择器 https://specificity.keegan.st/ 的特殊性。事实上,您需要根据您的设计调整固定更改