我遇到了chrome自动填充行为的几个形式的问题。

表单中的字段都有非常常见和准确的名称,例如“email”、“name”或“password”,并且它们还设置了autocomplete=“off”。

自动完成标志已经成功禁用了自动完成行为,当你开始输入时,会出现一个下拉的值,但没有改变Chrome自动填充字段的值。

这种行为是可以的,除了chrome填充输入不正确,例如填充电话输入与电子邮件地址。客户抱怨过这个问题,所以它被证实在很多情况下都发生了,而不是我在我的机器上本地操作的某种结果。

目前我能想到的唯一解决方案是动态生成自定义输入名称,然后在后端提取值,但这似乎是一种相当笨拙的解决这个问题的方法。是否有任何标签或怪癖,改变自动填充行为,可以用来解决这个问题?


当前回答

Finally I think I came with a decent solution. Understanding better how the dropdown works with Chrome helped :) Basically, the dropdown will be displayed when you focus the input and when you generate a mouse down event when you are typing an entry which matches with what Chrome has in memory. Keeping that in mind, and that Chrome does it for certain inputs when they have default names like "name", "email", etc. then we just need to remove the name when the dropdown is going to be displayed and add it back after :) I wanted to use a solution which can make it work just by adding the attribute autocomplete off. I thought it made sense. This is the code:

解决方案1

jQuery('body').on('mousedown','[name="name"][autocomplete="off"], [name="email"][autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    if(typeof this.currentName =="undefined")
        this.currentName=jQuery(this).attr('name');
    jQuery(this).attr('name','');
});

jQuery('body').on('blur','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    jQuery(this).attr('name',this.currentName);
});

解决方案2(我最喜欢的一个)

The solution I described above will remove the name of the input until we remove the focus (blur), in that moment it will put the original name back. But might happen that we are interested on having access to the input through its name attribute while we are typing. Which means that we need to put the name back right after each input. This solution, basically is based on the first solution. In this case, we will add the name on key down, and put it back on keyup. I think this is more neat for compatibility with what the "autocomplete off" behaviour should be. Anyway this is the code:

jQuery('body').on('mousedown keydown','[name="name"][autocomplete="off"], [name="email"][autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    if(typeof this.currentName =="undefined")
        this.currentName=jQuery(this).attr('name');
    jQuery(this).attr('name','');
});
jQuery('body').on('blur keyup','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    if(typeof this.currentName !="undefined")
        jQuery(this).attr('name',this.currentName);
});

请注意,对于解决方案1和2,我只采用输入名称为“name”和“email”的情况。对于任何其他情况下,这个属性使Chrome生成下拉,你将不得不添加它在选择器的鼠标下拉事件。

解决方案3

这个解决方案要复杂得多。我没有意识到我们试图纠正的行为只是基于那些带有特定名称的输入,如“姓名,电子邮件等”。这种解决方案的方法是在这种情况下,Chrome显示的其他名称,我们不知道一个先验。这将是一个非常通用的解决方案。我不像其他两个那样喜欢,主要是因为当我们按下删除键时,可能会有一个小闪烁。我会在下面解释。

我发现,下拉框出现在第二次点击输入后,而不是第一次点击时,当你第一次聚焦在输入上时。我为所有这些元素绑定了一个“mousedown”事件,其中处理程序基本上检测它是否已经聚焦在输入上,如果它检测到另一个“鼠标向下”,强制一个.blur(),然后是.focus(),防止第二次点击时的下拉。我希望,这是清楚的,以防万一,这是我使用的代码:

jQuery('body').on('mousedown','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    if(jQuery(this).is(':focus')) {
        jQuery(this).blur();
        jQuery(this).focus();
    }
});

In the other hand, in order to prevent the dropdown while you are typing in case it matches with Chrome suggestions... This is a little bit tricky. I just decided to replace the default behaviour of an input while user types. The dropdown evaluates the input on mouse down, so I prevent the default behaviour for alphanumerics, space, etc. The only problem is with Command,Ctrl and delete. For this case I had to bind also an event on mouse up. It allows the default behaviour in the first two cases so you can make copy, and paste, or select all. In the case of the delete, I have to allow the default behaviour, but if after deleting a character the input matches with Chrome suggestions, then again it was showing the dropdown. For this case I had to use the same trick of blur and focus. The only inconvenience I found on this is that since we are cancelling the behaviour on keyup, and chrome tries to show it on keydown, there is a small flicker. Anyway, this is the best I could do. Probably it will require for filtering of characters at one point. I just added the conditions made more sense for now. This is the second part of the code:

jQuery('body').on('keydown','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    var ctrlKey = 17,cmKey = 91;
    var charCode = e.which || e.keyCode;

    if(charCode!=16 && this.commandDown != true && this.ctrlDown != true && ((charCode>47 && charCode<58)||(charCode>64 && charCode<91)||(charCode>96 && charCode<123)||charCode==0 || charCode==32)){ 
        e.preventDefault();
        var charStr = String.fromCharCode(charCode);
        if(!e.shiftKey)
            charStr = charStr.toLowerCase(charStr);
        $(this).val($(this).val() + charStr);
    }else{
        if (charCode == cmKey) this.commandDown = true;
        if (charCode == ctrlKey) this.ctrlDown = true;
    }
});
jQuery('body').on('keyup','[autocomplete="off"]',function(e){
    e.stopImmediatePropagation();
    var allowed=[8];//Delete
    var ctrlKey = 17,cmKey = 91;
    var charCode = e.which || e.keyCode;

    if (charCode == cmKey) {this.commandDown = false};
    if (charCode == ctrlKey) {this.ctrlDown = false};
    if(allowed.indexOf(charCode)>=0 || (this.commandDown!=false && this.ctrlDown!=false)){
        jQuery(this).blur();
        jQuery(this).focus();
}

就像我说过的,这个解要复杂得多。这是我使用的第一个,直到我意识到下拉列表只出现在某些输入名称上。

抱歉写了这么多,我只是想确保一切都清楚。我希望这能有所帮助。

其他回答

除了autocomplete="off"外,还必须将值设置为空(value="")才能使其工作。

以下是我提出的解决方案,因为谷歌坚持推翻人们似乎做出的每一个变通办法。

选项1 -选择所有文本点击

为你的用户设置输入的值为一个例子(例如your@email.com),或者字段的标签(例如Email),并在你的输入中添加一个名为focus-select的类:

<input type="text" name="email" class="focus-select" value="your@email.com">
<input type="password" name="password" class="focus-select" value="password">

下面是jQuery:

$(document).on('click', '.focus-select', function(){
  $(this).select();
});

我真的看不出Chrome会搞砸数值。那太疯狂了。希望这是一个安全的解决方案。

选项2 -设置电子邮件值为一个空间,然后删除它

假设您有两个输入,例如电子邮件和密码,将电子邮件字段的值设置为“”(一个空格),并添加属性/值autocomplete=“off”,然后使用JavaScript清除此设置。您可以将密码值保留为空。

如果用户出于某种原因没有JavaScript,请确保您在服务器端修改了他们的输入(无论如何您都应该这样做),以防他们不删除空格。

下面是jQuery:

$(document).ready(function() {
  setTimeout(function(){
    $('[autocomplete=off]').val('');
  }, 15);
});

我将超时设置为15,因为5似乎在我的测试中偶尔可以工作,所以将这个数字增加三倍似乎是一个安全的赌注。

如果没有将初始值设置为空格,Chrome会让输入框显示为黄色,就好像它已经自动填充了一样。

选项3 -隐藏输入

把这个放在表单的开头:

<!-- Avoid Chrome autofill -->
<input name="email" class="hide">

CSS:

.hide{ display:none; }

确保您保留了HTML注释,这样其他开发人员就不会删除它!还要确保隐藏输入的名称是相关的。

在Chromium 53.0.2785.92(64位)上,以下工作

<div style="visibility:hidden">
    <input type="text" name="fake_username_remembered">
    <input type="password" name="fake_password_remembered">
</div>

显示:none不工作

对我来说很简单

<form autocomplete="off" role="presentation">

做到了。

在多个版本上进行了测试,最后一次尝试是在56.0.2924.87

这是我最近使用的解决方案。

$('#email').prop('autocomplete', true);