密码输入框封装,解决浏览器自动填充密码问题

1、引入组件:

import pwInput from '@/views/component/pwInput'
2、用法:
<pwInput v-model="form.oldPwd" @validatePass='validatePassOld' :showIcon='showIcon'></pwInput>
 
3、组件代码(此组件代码为网上找的,原来的有问题在ie浏览器中当有多个输入框时光标会上下跳动,解决了在ie浏览器光标来回闪烁问题):
<template>
    <!-- 这里使用了elemntUI的类名,如果没有安装elmentUI则自己自定义样式 -->
    <div class="pw_input_cp el-input">
         <svg v-if="showIcon" slot="prefix" style="margin-top: 7px;position:absolute;margin-left:5px" class="icon" aria-hidden="true">
            <use xlink:href="#icon-password"></use>
        </svg>
        <input 
            class="el-input__inner"
            :class="showIcon?'paddingInp':''"
            placeholder="请输入密码" 
            ref="input"
            @keyup="hanleKeyupEnter"
            @blur="handleBlur"
            @input="handleInput"
            @compositionstart="handleCompositionStart"
            @compositionend="handleCompositionEnd"/>
    </div>
</template>

<script>
//自定义密码输入框
//input元素光标操作
class CursorPosition{ 
    constructor(_inputEl) {
        this._inputEl = _inputEl;
    } 
    //获取光标的位置 前,后,以及中间字符
    get(){  
        var rangeData = { text: "", start: 0, end: 0 };  
        if (this._inputEl.setSelectionRange) { // W3C      
            // this._inputEl.focus();  
            rangeData.start = this._inputEl.selectionStart;  
            rangeData.end = this._inputEl.selectionEnd;  
            rangeData.text = (rangeData.start != rangeData.end) ? this._inputEl.value.substring(rangeData.start, rangeData.end) : "";  
        } else if (document.selection) { // IE  
            // this._inputEl.focus();  
            var i,  
                oS = document.selection.createRange(),  
                oR = document.body.createTextRange();  
            oR.moveToElementText(this._inputEl);  

            rangeData.text = oS.text;  
            rangeData.bookmark = oS.getBookmark();  
            for (i = 0; oR.compareEndPoints('StartToStart', oS) < 0 && oS.moveStart("character", -1) !== 0; i++) {  
                if (this._inputEl.value.charAt(i) == '\r') {  
                    i++;  
                }  
            }  
            rangeData.start = i;  
            rangeData.end = rangeData.text.length + rangeData.start;  
        }  

        return rangeData;  
    } 
    // //写入光标的位置
    set(rangeData){  
        var oR;  
        if (!rangeData) {  
            alert("You must get cursor position first.")  
        }  
        // this._inputEl.focus();  
        if (this._inputEl.setSelectionRange) { // W3C  
            this._inputEl.setSelectionRange(rangeData.start, rangeData.end);  
        } else if (this._inputEl.createTextRange) { // IE  
            oR = this._inputEl.createTextRange();  
            if (this._inputEl.value.length === rangeData.start) {  
                oR.collapse(false);  
                oR.select();  
            } else {  
                oR.moveToBookmark(rangeData.bookmark);  
                oR.select();  
            }  
        }  
    }
}
export default { 
    name: 'Pw_input_cp',
    props:{
        value:{
            type:String,
            default:"",
        },
        validatePass:Function,
        login:Function,
        showIcon:{
            type:Boolean,
            default:true
        }
    },
    data(){
        return{
            symbol:"*", //自定义的密码符号
            pwd:"", //密码明文数据
            inputEl:null, //input元素
            isComposing:false, //输入框是否还在输入(记录输入框输入的是虚拟文本还是已确定文本)
        };
    },
    mounted(){
        this.$refs.input.blur()
        this.inputEl = this.$refs.input;
    },
    computed:{
        value(){
            this.pwd = this.value;
            this.inputDataConversion(this.pwd);
        }
    },
    // watch:{
    //     value(){
    //         this.pwd = this.value;
    //         this.inputDataConversion(this.pwd);
    //     },
    // },
    methods:{
        inputDataConversion(value){ //输入框里的数据转换,将123转为***
            if (!value){
                this.inputEl.value = "";
                return;
            };
            let data = "";
            for(let i=0;i<value.length;i++){
                data+=this.symbol;
            }
            this.inputEl.value = data;
        },
        pwdSetData(positionIndex,value){ //写入原始数据
            let _pwd = value.split(this.symbol).join("");
            if(_pwd){
                let index = this.pwd.length - (value.length - positionIndex.end);
                this.pwd = this.pwd.slice(0,positionIndex.end-_pwd.length) + _pwd + this.pwd.slice(index);
            }else{
                this.pwd = this.pwd.slice(0,positionIndex.end) + this.pwd.slice(positionIndex.end+this.pwd.length - value.length);
            }
        },
        handleInput(e){ //输入值变化后执行
            window.event? window.event.cancelBubble = true : e.stopPropagation();
            if(e.preventDefault){
                e.preventDefault();
            }else{
                window.event.returnValue == false;
            }
            //撰写期间不应发出输入
            if (this.isComposing) return;
            let cursorPosition = new CursorPosition(this.inputEl);
            let positionIndex = cursorPosition.get();
            let value = e.target.value; //整个输入框的值
            this.pwdSetData(positionIndex,value);
            this.inputDataConversion(value);
            // cursorPosition.set(positionIndex,this.inputEl);
            this.$emit("input",this.pwd);
        },
        handleBlur(){
            this.$emit("validatePass",this.pwd);
        },
        hanleKeyupEnter(event){
            let keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
            if(keyCode==13){
                this.$emit("login");
            }
        },
        handleCompositionStart() {
            //表示正在写
            this.isComposing = true;
        },
        handleCompositionEnd(e) {
            if (this.isComposing) {
                this.isComposing = false;
                //handleCompositionEnd比handleInput后执行,避免isComposing还为true时handleInput无法执行正确逻辑
                this.handleInput(e);
            }
        },
    },
}
</script>

<style scoped lang="scss">
.pw_input_cp{
    width: 100%;
    .el-input__inner{
        
    }
    .paddingInp{
        padding-left: 35px;
        padding-top: 3px;
    }
}
</style>
posted @ 2021-04-01 16:39  诺克萨斯小刀  阅读(312)  评论(0编辑  收藏  举报