我遇到了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();
}

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

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

其他回答

我想我该把我的药发上去。发现你不能使用显示:没有,所以我想出了一个快速和肮脏的解决方案,只是使假输入小,并将其移出视线。到目前为止一切顺利,直到他们再次打破它。

<input id="FakePassword" type="password" style="float:left;position:relative;height:0;width:0;top:-1000px;/>

这些问题的其他解决方法对我都不起作用。

唯一管用的想法是这个:

它从元素中删除“name”和“id”属性并为它们赋值 1毫秒后返回。把这个放在文件里,准备好。

$(document).ready(function() {
    $('form[autocomplete="off"] input, input[autocomplete="off"]').each(function () {

                var input = this;
                var name = $(input).attr('name');
                var id = $(input).attr('id');

                $(input).removeAttr('name');
                $(input).removeAttr('id');

                setTimeout(function () {
                    $(input).attr('name', name);
                    $(input).attr('id', id);
                }, 1);
            });
});

好吧,因为我们都有这个问题,我花了一些时间来写一个工作的jQuery扩展这个问题。谷歌必须遵循html标记,而不是我们遵循谷歌

(function ($) {

"use strict";

$.fn.autoCompleteFix = function(opt) {
    var ro = 'readonly', settings = $.extend({
        attribute : 'autocomplete',
        trigger : {
            disable : ["off"],
            enable : ["on"]
        },
        focus : function() {
            $(this).removeAttr(ro);
        },
        force : false
    }, opt);

    $(this).each(function(i, el) {
        el = $(el);

        if(el.is('form')) {
            var force = (-1 !== $.inArray(el.attr(settings.attribute), settings.trigger.disable))
            el.find('input').autoCompleteFix({force:force});
        } else {
            var disabled = -1 !== $.inArray(el.attr(settings.attribute), settings.trigger.disable);
            var enabled = -1 !== $.inArray(el.attr(settings.attribute), settings.trigger.enable);
            if (settings.force && !enabled || disabled)
                el.attr(ro, ro).focus(settings.focus).val("");
        }
    });
};
})(jQuery);

只需将其添加到/js/ jQuery. extensions .js这样的文件中,并将其包含在jQuery之外。 将它应用到加载文档时的每个表单元素,如下所示:

$(function() {
    $('form').autoCompleteFix();
});

Jsfiddle测试

纯HTML解决方案:

(不需要javascript,不需要css,不需要隐藏输入)

<form autoComplete="new-password" ... >
        <input name="myInput" type="text" autoComplete="off" id="myInput" placeholder="Search field" />
</form>

注:

表单不一定是输入元素的直接父元素 Input需要一个name属性

我不知道为什么,但这对我很有帮助。

<input type="password" name="pwd" autocomplete="new-password">

我不知道为什么,但autocomplete="new-password"禁用自动填充。它在最新的49.0.2623.112 chrome版本中工作。