禁止input密码自动填充及浏览器记住密码完整解决方案

完整方案

禁止缓存,禁止自动填充,不会触发浏览提示记住密码,其余与正常一致,该方案跨浏览器兼容且易结合任何框架及库使用。

npm i nice-pass-word

具体使用参照文档既可以。
下面的内容是应用场景中的具体问题和目前解决方案的不足以及nicepassword解决了哪些问题。

禁止自动填充方案
  readonly  onfocus="this.removeAttribute('readonly')" 

这方案亲测有效,简单直接,把上面代码直接复制放到input标签就上就行。
ps:现有的网上多数加隐藏input获取值,都是解决默认填充的,而剩下的方案都是只能实现部分功能。

但是这个方案 如果使用password还是会引起浏览器提醒是否保存密码,并不能禁用缓存,只能不自动把账号密码填充进去。

为了,当type="password"的时候,做了以下测试:

  1. 动态设置,初始化为了text,输入之后变为password。失败:在谷歌上,只要设置过password这个input就能引起浏览器反应(出现钥匙的标签,继而提交的时候弹出提示)。
  2. 因为是input为空的时候,钥匙会消失。输入值就会出现,并且js操作的值和初始化值的不会出现钥匙,所以能不能把这个动作禁止了,浏览器接受不到就不出现。按照DOM事件的思路,禁用了input的所有事件的冒泡,默认事件,无效。失败:完全不知道浏览器是怎么触发得。
  3. 继而放弃禁止出现钥匙,那么表单提交动作浏览器能不能禁止,一堆操作禁止,失败:同2一样浏览器并不是在事件机制接受到的触发,或者是在我们事件机制之前?不得而知
  4. 至此,原生的passwraod已经没有思路来解决这个问题(如果有请留言,作者尝试后更新文章),那么我们就来打造了一个password
禁止记住密码方案

首先,什么都不说,直接上代码(下载下载不了直接去文章末尾复制)。
引入js后,你只需要:

   <input type="text" id="password"  value="123456a" autocomplete="off">
    var password = new Text2Password({
        id: "password",
        // type:"password", // password 转化为* 其他直接显示
        // pattern: /([\u4e00-\u9fa5])/g ,// 接受一个正则,过滤匹配内容
        // symbol:"*",// 接受一个字符 作为隐藏的是占位符
        callback: function () {
            // 数据改变后的回调
            console.log(this.value)
        }
    });
    // password.value 取值
    // password.$changeType(type)  切换显示状态 传入'password'隐藏 其余正常显示
    // password.$setValue(value)   设置值(初始值会自动初始化) 

已实现功能:

  1. 隐藏真实值。
  2. 解决浏览器记住密码,自动填充,自动弹出记住密码的提示。
  3. 禁止复制,剪切,拖拽,允许粘贴。
  4. 可以在任意位置进行数据插入,删除,替换。
  5. 兼容中文输出(默认正则会过滤中文,但是输入法输入的字母可以正常被输入。)
  6. 兼容谷歌,ie,火狐

ps:ie可以配合style="ime-mode:disabled"禁用中文输入法,为了保持浏览器展现形式一致,没有默认添加。

如果有更好的方法,或者上述代码有bug,请留言一起交流,作者会长期更新。

附录:vue 组件版本
使用方法:

  Vue.use(PassWordPlugin)
  <pass-word :value="value"  :type="type"></pass-word>

切换数据,按照Vue模式操作传入的valuetype即可,监听了后续数据变化。
与纯js版本一样,也接受symbolpattern.

能正常下载代码的童鞋不用往下看了 ==

js版本 Text2Password.js

; (function (name, definition) {
    if (typeof define === 'function') {
        define(definition);
    } else if (typeof module !== 'undefined' && module.exports) {
        module.exports = definition();
    } else {
        this[name] = definition();
    }
})('Text2Password', function () {
    "use strict";
    function Text2Password (opts) {
        var id = opts.id,
            _opts$type = opts.type,
            type = _opts$type === void 0 ? 'password' : _opts$type,
            _opts$symbol = opts.symbol,
            symbol = _opts$symbol === void 0 ? '*' : _opts$symbol,
            _opts$callback = opts.callback,
            callback = _opts$callback === void 0 ? function () { } : _opts$callback,
            _opts$pattern = opts.pattern,
            pattern = _opts$pattern === void 0 ? /([\u4e00-\u9fa5])/g : _opts$pattern,
            _this = this;

        _this.input = document.getElementById(id);

        if (!_this.input || _this.input.tagName.toLowerCase() != 'input' || _this.input.type === 'password') {
            throw new Error("请传一个type不为password的input的id属性!");
            return;
        }

        _this.input.valueProxy = "";
        _this.callback = callback;
        _this.type = type;
        _this.symbol = symbol;
        _this.pattern = pattern;
        _this.cursor = 0;
        _this.isInit = false;
        Object.defineProperty(_this, 'value', {
            get: function get () {
                return _this.input.valueProxy;
            }
        });

        _this.init();

        return _this;
    }

    Text2Password.prototype.init = function () {
        this.$setValue(); // 设置初始值

        this._preventDefaultEvent(); //阻止input type=text 的默认操作 使其比较相似与password


        this._bindEvent(); // 绑定事件 转化数据 =》 符号


        this.isInit = true;
    }; // 阻止复制 剪切  拖拽进入 拖拽离开


    Text2Password.prototype._preventDefaultEvent = function (e) {
        function _preventDefaultHandler (e) {
            var e = e || window.event;
            e.preventDefault();
        }

        function _mousedownHandler (e) {
            if (e.button === 0 && this.selectionStart != this.selectionEnd) {
                this.selectionStart = this.selectionEnd = this.value.length;
            }

            return false;
        }

        function _dragleaveHandler (e) {
            e.preventDefault();
            this.warn("_dragleaveHandler");
            this.removeAttribute('readonly');
            return false;
        }

        function _dragenterhandlder (e) {
            e.preventDefault();
            this.warn("_dragenterhandlder");
            this.setAttribute('readonly', true);
            return false;
        }

        this.input.addEventListener("copy", _preventDefaultHandler);
        this.input.addEventListener("cut", _preventDefaultHandler);
        this.input.addEventListener("dragenter", _dragenterhandlder);
        this.input.addEventListener("dragleave", _dragleaveHandler);
        this.input.addEventListener("mousedown", _mousedownHandler);
    };

    Text2Password.prototype._bindEvent = function () {
        var _this2 = this;

        this.input.addEventListener("compositionstart", function () {
            _this2.lock = true;

            _this2.warn("start");
        });
        this.input.addEventListener("compositionend", function () {
            _this2.lock = false;

            _this2.warn("end");

            _this2._inputHandler();
        });
        this.input.addEventListener("input", this._inputHandler.bind(this));
        this.input.addEventListener("propertychange", this._inputHandler.bind(this));
    };

    Text2Password.prototype._inputHandler = function () {
        if (this.lock) return;

        if (!this.isInit) {
            this.warn('init');
        } else {
            this.warn('input');
        }

        if (this.type === 'password') {
            this._passwordHandler();
        } else {
            this._textHandler();
        }

        this._showValue();

        this._setCursor();

        typeof this.callback == "function" && this.callback();
    };

    Text2Password.prototype._passwordHandler = function () {
        var _this = this,
            cvalueArr = this._filterCn(this.input.value).split(""),
            ovalueArr = this.input.valueProxy.split(""),
            clen = cvalueArr.length - ovalueArr.length,
            cursor = this.input.selectionStart,
            ccursor = cursor - this.input.value.split("").length + cvalueArr.length,
            sidx = "",
            eidx = "";

        if (clen > 0) {
            var inArr = cvalueArr.join("").replace(/\*/g, "").split("");
            var right = cvalueArr.length - cursor > 0 ? ovalueArr.slice(-(cvalueArr.length - cursor)) : [];
            ovalueArr = [].concat(ovalueArr.slice(0, cursor - inArr.length), inArr, right);
        }

        if (clen < 0) {
            ovalueArr.splice(cursor, Math.abs(clen));
        }

        cvalueArr.forEach(function (value, index) {
            if (value != "*") {
                ovalueArr[index] = value;
            }
        });
        this.input.valueProxy = ovalueArr.join("");
        this.cursor = ccursor;
    };

    Text2Password.prototype._filterCn = function _filterCn (str, repStr) {
        if (!str) return str;
        var pattern = this.pattern,
            repStr = repStr ? repStr : "";
        return str.replace(pattern, repStr);
    };

    Text2Password.prototype._textHandler = function () {
        this.input.valueProxy = this._filterCn(this.input.value);
        this.cursor = this.input.selectionStart - this.input.value.split("").length + this.input.valueProxy.split("").length;
    };

    Text2Password.prototype._showValue = function () {
        var _this3 = this;

        var str = "";

        if (this.type === 'password') {
            this.value.split("").forEach(function (val) {
                str += _this3.symbol;
            });
        } else {
            str = this.value;
        }

        this.input.value = str;
    };

    Text2Password.prototype._setCursor = function () {
        this.input.selectionStart = this.cursor;
        this.input.selectionEnd = this.cursor;
    };

    Text2Password.prototype.warn = function (msg) {
        console.log(msg);
    };

    Text2Password.prototype.$setValue = function (value) {
        if (value) this.input.value = value;

        this._inputHandler();
    };

    Text2Password.prototype.$changeType = function (type) {
        this.type = type;
        this.$setValue(this.value);
    };

    return Text2Password;
});

vue组件版本 passWord.js

; (function (name, definition) {
    if (typeof define === 'function') {
        define(definition);
    } else if (typeof module !== 'undefined' && module.exports) {
        module.exports = definition();
    } else {
        this[name] = definition();
    }
})('PassWordPlugin', function () {
   'use strict';
    return {
        install: function (value) {
            Vue.component("pass-word", {
                template: '<input                            \
                                style="ime-mode:disabled"        \
                                autocomplete="off"               \
                                ref="pw-input"                   \
                                :value="showValue"               \
                                type="text"                      \
                                @input="cinput"                  \
                                @copy.prevent=""                 \
                                @cut.prevent=""                  \
                                @compositionstart.prevent="_compositionstartHandler"              \
                                @compositionend.prevent="_compositionendHandler"                  \
                                @dragenter="_dragenterhandlder"  \
                                @dragleave="_dragleaveHandler"   \
                                @mousedown="_mousedownHandler"   \
                                />',
                props: {
                    type: {
                        type: String,
                        default: 'password'
                    },
                    value: {
                        type: String,
                        default: ""
                    },
                    symbol: {
                        type: String,
                        default: "*"
                    },
                    pattern: {
                        type: RegExp,
                        default: function () {
                            return /([\u4e00-\u9fa5])/g
                        }
                    }
                },
                data: function data () {
                    return {
                        valueProxy: ""
                    };
                },
                computed: {
                    showValue: function showValue () {
                        if (this.type != "password") {
                            return this.valueProxy;
                        }
                        return this.fillSymbol();
                    }
                },
                watch: {
                    value: function value (newval) {
                        if (newval != this.valueProxy) this._initValue();
                    }
                },
                mounted: function mounted () {
                    this._initValue();
                },
                methods: {
                    _compositionstartHandler: function () {
                        this.lock = true;
                        console.log("start")
                    },
                    _compositionendHandler: function (e) {
                        this.lock = false;
                        console.log("end")
                        if (e.target.composing === undefined) this.cinput();// 兼容Vue版本 有composing属性的版本会自动触发一次cinput  
                    },
                    _mousedownHandler: function (e) {
                        if (e.button === 0 && (this.$refs['pw-input'].selectionStart != this.$refs['pw-input'].selectionEnd)) {
                            this.$refs['pw-input'].selectionStart = this.$refs['pw-input'].selectionEnd = this.valueProxy.length;
                        }
                        return false
                    },
                    _dragleaveHandler: function (e) {
                        e.preventDefault();
                        // console.log("_dragleaveHandler")
                        this.$refs['pw-input'].removeAttribute('readonly')
                        return false
                    },
                    _dragenterhandlder: function (e) {
                        e.preventDefault();
                        // console.log("_dragenterhandlder")
                        this.$refs['pw-input'].setAttribute('readonly', true)
                        return false
                    },
                    _filterCn: function _filterCn (str, repStr) {
                        if (!str) return str;
                        var pattern = this.pattern,
                            repStr = repStr ? repStr : "";
                        return str.replace(pattern, repStr);
                    },
                    _initValue: function _initValue () {
                        var value = this.value
                        if (value == undefined || value == null) value = "";
                        this.valueProxy = this._filterCn(value);
                        this.$emit('input', this.valueProxy);
                    },
                    _inputHandler: function _inputHandler () {

                        var _this = this;

                        var cvalueArr = this._filterCn(this.$refs['pw-input'].value).split(""),
                            ovalueArr = this.valueProxy.split(""),
                            clen = cvalueArr.length - ovalueArr.length,
                            cursor = this.$refs['pw-input'].selectionStart,
                            ccursor = cursor - this.$refs['pw-input'].value.split("").length + cvalueArr.length,
                            sidx = "",
                            eidx = "";


                        if (clen > 0) {
                            var inArr = cvalueArr.join("").replace(/\*/g, "").split("");
                            var right = cvalueArr.length - cursor > 0 ? ovalueArr.slice(-(cvalueArr.length - cursor)) : [];
                            ovalueArr = [].concat(ovalueArr.slice(0, cursor - inArr.length), inArr, right);
                        }

                        if (clen < 0) {
                            ovalueArr.splice(cursor, Math.abs(clen));
                        }

                        cvalueArr.forEach(function (value, index) {
                            if (value != "*") {
                                ovalueArr[index] = value;
                            }
                        });

                        if (this.valueProxy == ovalueArr.join("")) {
                            this.$forceUpdate();
                        } else {
                            this.valueProxy = ovalueArr.join("");
                        }

                        this.$nextTick(function () {
                            _this.$refs['pw-input'].selectionStart = ccursor;
                            _this.$refs['pw-input'].selectionEnd = ccursor;
                        });
                    },
                    cinput: function cinput (e) {
                        if (this.lock) return;
                        console.log('input')
                        if (this.type != 'password') {
                            this.valueProxy = this._filterCn(this.$refs['pw-input'].value);
                            this.$forceUpdate();
                        } else {
                            this._inputHandler();
                        }
                        this.$emit('input', this.valueProxy);
                    },
                    fillSymbol: function fillSymbol () {
                        var symbolstr = "";
                        for (var i = 0, len = this.valueProxy.length; i < len; i++) {
                            symbolstr += this.symbol;
                        }
                        return symbolstr;
                    }
                }
            });
        }
    }
})

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值