vue 根据element-ui 自定义密码输入框,防止浏览器 记住密码和自动填充
<template><divclass="el-password el-input":class="[size ? 'el-input--' + size : '', { 'is-disabled': disabled }]"><inputclass="el-input__inner":placeholder="placeholder"ref="input":style="{ paddingRight: padding + 'px' }":disabled="disabled":readonly="readonly"@focus="handleFocus"@blur="handleBlur"@input="handleInput"@change="change"@compositionstart="handleCompositionStart"@compositionend="handleCompositionEnd"/><div class="tools"><iv-if="clearable !== false"v-show="pwd !== '' && isfocus"@mousedown.preventclass="el-input__icon el-icon-circle-close el-input__clear"@click="clearValue"></i><iv-if="showPassword !== false"v-show="pwd !== '' || isfocus"class="el-input__icon el-icon-view el-input__clear"@click="changePasswordShow"></i></div></div>
</template> <script>
import emitter from "element-ui/src/mixins/emitter";
//自定义密码输入框//input元素光标操作
class CursorPosition {constructor(_inputEl) {this._inputEl = _inputEl;}//获取光标的位置 前,后,以及中间字符get() {var rangeData = { text: "", start: 0, end: 0 };if (this._inputEl.setSelectionRange) {// W3Cthis._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) {// IEthis._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) {// W3Cthis._inputEl.setSelectionRange(rangeData.start, rangeData.end);} else if (this._inputEl.createTextRange) {// IEoR = 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: "" },size: { type: String, 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);},mixins: [emitter],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: {select() {this.$refs.input.select();},focus() {this.$refs.input.focus();},blur() {this.$refs.input.blur();},handleFocus(event) {this.isfocus = true;this.$emit("focus", event);},handleBlur(event) {this.isfocus = false;this.$emit("blur", event);//校验表单this.dispatch("ElFormItem", "el.form.blur", [this.value]);},change(...args) {this.$emit("change", ...args);},clearValue() {this.pwd = "";this.inputEl.value = "";this.$emit("input", "");this.$emit("change", "");this.$emit("clear");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;}//使用元素的dataset属性来存储和访问自定义数据-*属性 (存储转换前数据)this.inputEl.dataset.value= this.pwd;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;//整个输入框的值if (this.show) {this.pwd = value;} else {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: 5px;display: flex;align-items: center;top: 0;height: 100%;z-index: 1;
}
</style>
引用组件
<template><div><el-formstyle="width: 320px; margin: 50px auto":model="fromData"ref="elfrom":rules="rules"><el-form-item label="密码" prop="password"><el-passwordsize="small"v-model="fromData.password"show-passwordplaceholder="请输入密码"></el-password></el-form-item><el-form-item label="确认密码" prop="confirmPassword"><el-passwordsize="small"v-model="fromData.confirmPassword"show-passwordplaceholder="请再次输入密码"></el-password></el-form-item></el-form><br /></div>
</template>
<script>
import elPassword from "./el-password.vue";
export default {data() {return {fromData: {password: "",confirmPassword: "",},rules: {password: [{required: true,validator: (rule, value, callback) => {if (!value) {callback(new Error("请输入密码"));} else if (/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[^a-zA-Z0-9]).{10,20}$/.test(value) === true) {callback();} else {callback(new Error("密码范围在10~20位之间!须包含字母数字特殊符号"));}},trigger: "blur",},],confirmPassword: [{required: true,validator: (rule, value, callback) => {if (!value) {callback(new Error("请输入确认密码"));} else if (value != this.fromData.password) {callback(new Error("二次密码不一致"));} else {callback();}},trigger: "blur",},],},};},components: {elPassword,},
};
</script>