如题,在vue的技术架构上的实现,这是其中的一种方式:
- input 元素 type = text;
- 将输出的明文字符转换成密码符号 • ;
如下以 vue 编码:
<el-input
id="pwdConfirm"
ref="pwdConfirm"
type="text"
v-model="form.pwdConfirm"
@paste.native="pastePwd($event)"
@input.native="
inputPwd(
$event,
'pwdConfirm',
'pwdConfirm',
'pwdConfirm'
)
"
@compositionend.native="
compositionend(
$event,
'pwdConfirm',
'pwdConfirm',
'pwdConfirm'
)
"
autocomplete="new-password">
</el-input>
......
事件的回调如下:
// e: $event 事件句柄
// prop: 没用
// ref: dom元素的id
// stored: 定义的存储该元素值的变量名
inputPwd(e, prop, ref, stored) {
//input text 字符串替换为实心圆password显示
let type = e.inputType;
if (type === "deleteContentBackward") { // 按下 “Backspace” 时
this.form[prop] = "";
this[stored] = "";
} else if (type === "deleteContentForward") { // 按下 "Delete" 时
let stArr = this[stored].split("");
stArr.splice(e.target.selectionStart, 1);
this[stored] = stArr.join("");
} else if (type !== "historyUndo") { // 非 回退(ctrl+z) 时
// Safari 中文输入 需要特殊处理
if (this.isMac && type !== "insertText" && type !== "insertFromPaste") {
this.macPwd(e, prop, stored);
return;
}
if (type === "insertCompositionText") { // 中文输入
this.focusSelection = this[stored].length + e.data.length;
} else {
let plus = this.prePaste;
if (type === "insertText") {
// insertFromComposition Safari上中文输入最后输出事件
plus = e.data.trim();
}
// 当在字符串中进行输入或者粘贴新的字符串时
if (this[stored].length + plus.length >= e.target.selectionStart) {
// 光标在原值中进行粘贴
let selectionEnd = e.target.selectionStart - plus.length; // e.target.selectionStart 从1开始 为事件触发后的光标起始位置
let start = this[stored].substr(0, selectionEnd);
let rest = this[stored].substr(selectionEnd);
let newStart = start + plus.trim();
this[stored] = newStart + rest;
this.focusSelection = selectionEnd + plus.length;
} else {
this[stored] += plus;
}
}
this.convertToRound(prop, ref, stored);
}
this.$forceUpdate();
},
macPwd(e, prop, stored) {
// 中文输入时 Safari 直接提示密码规则
if (e.inputType == "insertFromComposition") {
this.$messageError({
message: "请输入6-18位字母、数字或下划线(至少两种)",
});
this.focusSelection = e.target.selectionStart;
this[stored] = "";
this.form[prop] = "";
this.$forceUpdate();
}
},
// 将存储的this[stored] 转换为 •
async convertToRound(prop, ref, stored) {
// 通过stored 转换form[prop] 显示在输入框上
this.form[prop] = this[stored].replace(/./g, "•");
// 将光标置于更新后的位置
await this.$nextTick(); // dom更新,则光标会更新
let input = document.getElementById(ref);
if (input.setSelectionRange) { // input.setSelectionRange 为手动设置光标位置
input.focus();
input.setSelectionRange(this.focusSelection, this.focusSelection);
}
},
// 中文输入最后按下空格键输出时 触发
compositionend(e, prop, ref, stored) {
this[stored] += e.data;
this.convertToRound(prop, ref, stored);
},
// 粘贴事件触发,记录粘贴的内容
pastePwd(e) {
let text = e.clipboardData.getData("Text");
this.prePaste = text;
},
input 输入框上面触发的一些事件如下:
- 输入事件:@input.native
- 中文开始输入事件:@compositionstart.native
- 中文结束输入事件:@compositionend.native
- 粘贴事件:@paste.native
执行优先顺序:
- compositionstart > input > compositionend;
- paste > input