vue 仿element-ui 自定义密码输入框,防止浏览器 记住密码和自动填充

发布时间:2023年12月26日

vue 仿element-ui 自定义密码输入框,防止浏览器 记住密码和自动填充

<template>
  <div class="el-password el-input">
    <input
      class="el-input__inner"
      :placeholder="placeholder"
      ref="input"
      :style="{ paddingRight: padding + 'px' }"
      :disabled="disabled"
      :readonly="readonly"
      @focus="isfocus = true"
      @blur="isfocus = false"
      @input="handleInput"
      @compositionstart="handleCompositionStart"
      @compositionend="handleCompositionEnd"
    />
    <div class="tools">
      <i
        v-if="clearable !== false"
        v-show="pwd !== ''"
        :style="{ opacity: isfocus ? '1' : '0' }"
        class="el-icon-circle-close"
        @click="clearValue"
      ></i>
      <i
        v-if="showPassword !== false"
        v-show="pwd !== '' || isfocus"
        class="el-icon-view"
        @click="changePasswordShow"
      ></i>
    </div>
  </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) {
      console.warn("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: "el-password",
  props: {
    value: { default: "" },
    placeholder: { type: String, default: "请输入" },
    disabled: { type: [Boolean, String], default: false },
    readonly: { type: [Boolean, String], default: false },
    clearable: { type: [Boolean, String], default: false },
    showPassword: { type: [Boolean, String], default: false },
  },
  data() {
    return {
      symbol: "●", //自定义的密码符号
      pwd: "", //密码明文数据
      padding: 15,
      show: false,
      isfocus: false,
      inputEl: null, //input元素
      isComposing: false, //输入框是否还在输入(记录输入框输入的是虚拟文本还是已确定文本)
    };
  },
  mounted() {
    this.inputEl = this.$refs.input;

    this.pwd = this.value;
    this.inputDataConversion(this.pwd);
  },
  watch: {
    value: {
      handler: function (value) {
        if (this.inputEl) {
          this.pwd = value;
          this.inputDataConversion(this.pwd);
        }
      },
    },
    showPassword: {
      handler: function (value) {
        let padding = 15;
        if (value) {
          padding += 18;
        }
        if (this.clearable) {
          padding += 18;
        }
        this.padding = padding;
      },
      immediate: true,
    },
    clearable: {
      handler: function (value) {
        let padding = 15;
        if (value) {
          padding += 18;
        }
        if (this.showPassword) {
          padding += 18;
        }
        this.padding = padding;
      },
      immediate: true,
    },
  },
  methods: {
    clearValue() {
      this.pwd = "";
      this.inputEl.value = "";
      this.$emit("input", this.pwd);
      this.$refs.input.focus();
    },
    changePasswordShow() {
      this.show = !this.show;
      this.inputDataConversion(this.pwd);
      this.$refs.input.focus();
    },
    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 = this.show ? this.pwd : 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) {
      //输入值变化后执行 //撰写期间不应发出输入
      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);
    },
    handleCompositionStart() {
      //表示正在写
      this.isComposing = true;
    },
    handleCompositionEnd(e) {
      if (this.isComposing) {
        this.isComposing = false;
        //handleCompositionEnd比handleInput后执行,避免isComposing还为true时handleInput无法执行正确逻辑
        this.handleInput(e);
      }
    },
  },
};
</script>

<style scoped>
.tools {
  position: absolute;
  right: 0px;
  display: flex;
  align-items: center;
  top: 0;
  height: 100%;
  z-index: 1;
}

.tools i {
  cursor: pointer;
  margin-right: 10px;

  color: #c0c4cc;
}
.tools i:hover {
  color: #9fa3aa;
}
</style>

引用组件

<template>
  <div>
    <el-password v-model="password" show-password :placeholder="'输入密码'">
    </el-password>
    <el-input v-model="password" placeholder="测试v-model"></el-input>
  </div>
</template>
<script>
import elPassword from "./el-password.vue";
export default {
  data() {
    return { password: "" };
  },
  components: {
    elPassword,
  },
};
</script>
        
 
文章来源:https://blog.csdn.net/qq_43294510/article/details/135218429
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。